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