CF451E Devu and Flowers 解题报告

CF451E Devu and Flowers

题意:

(Devu)(N)个盒子,第(i)个盒子中有(c_i)枝花。同一个盒子内的花颜色相同,不同盒子的花颜色不同。(Devu)要从中选出(M)枝花,求有多少种方案,对(10e9+7)取模。

数据范围

(1 le N le 20,0 le M le 10^{14},0 le c_i le 10^{12})


其实就是求多重集组合数的模板题。

可以看看我写的博客

一些注意点,发现直接求会爆(long long)(lucas)一下免得爆了

注意(M)很大(N)很小,所以先把((M-N)!)除掉再算复杂度就是对的了


Code:

#include <cstdio>
#define ll long long
const ll mod=1e9+7;
ll quickpow(ll d,ll k)
{
    ll f=1;
    while(k)
    {
        if(k&1) f=f*d%mod;
        d=d*d%mod;
        k>>=1;
    }
    return f;
}
ll cal(ll r,ll l)
{
    ll s=1;
    for(ll i=r;i>l;i--) (s*=i)%=mod;
    return s;
}
ll inv[22];
ll C(ll m,ll n)
{
    if(m<n) return 0;
    if(n==0) return 1;
    if(m<mod) return cal(m,m-n)*inv[n]%mod;
    return C(m/mod,n/mod)*C(m%mod,n%mod)%mod;
}
ll n,s,f[23];
int main()
{
    scanf("%lld%lld",&n,&s);
    ll fac=1;
    for(ll i=1;i<=n;i++)
    {
        fac=fac*i%mod;
        inv[i]=quickpow(fac,mod-2);
        scanf("%lld",f+i);
    }
    ll ans=0;
    for(int i=0;i<1<<n;i++)
    {
        ll m=s+n-1,cnt=0;
        for(int j=0;j<n;j++)
            if(i>>j&1)
                m-=f[j+1],cnt++;
        (ans+=(cnt&1?-1ll:1ll)*C(m-cnt,n-1))%=mod;
    }
    printf("%lld
",(ans%mod+mod)%mod);
    return 0;
}

2018.10,17

原文地址:https://www.cnblogs.com/butterflydew/p/9805589.html