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\n",(ans%mod+mod)%mod);
    return 0;
}

2018.10,17

posted @ 2018-10-17 17:33  露迭月  阅读(271)  评论(0编辑  收藏  举报