女神的微笑---------------多重集的组合数,容斥原理
此题为多重集的组合数的 模板题 。
根据容斥原理,暴力枚举所有子集合,并且算出当前子集合中的元素取法全为不合法的方案数。
然后根据容斥公式计算答案。
1 #include<bits/stdc++.h> 2 #define ll long long 3 #define p 1000000007 4 using namespace std; 5 int g[2000050]; 6 ll f[25],m,n,ans; 7 ll ksm(ll u,ll v) 8 { 9 if(!v) 10 return 1; 11 ll tmp=ksm(u,v>>1); 12 (tmp*=tmp)%=p; 13 if(v&1) 14 (tmp*=u)%=p; 15 return tmp; 16 } 17 ll C(ll N,ll M) 18 { 19 if(!M) return 1; 20 if(N<M) return 0; 21 ll a=C(N/p,M/p),b=1; 22 for(ll i=0;i<M;++i) 23 (a*=(N-i)%p)%=p; 24 for(ll i=1;i<=M;++i) 25 (b*=i%p)%=p; 26 return a*ksm(b,p-2)%p; 27 } 28 int main() 29 { 30 scanf("%lld%lld",&n,&m); 31 for(int i=0;i<n;++i) 32 scanf("%lld",&f[i]); 33 for(int i=0;i<(1<<n);++i) 34 { 35 ll s=m;g[i]=g[i>>1]+(i&1); 36 for(int j=0;j<n;++j) 37 if(i&(1<<j)) s-=f[j]+1; 38 if(g[i]&1) (ans-=C(s+n-1,n-1)-p)%=p; 39 else (ans+=C(s+n-1,n-1))%=p; 40 } 41 printf("%lld",ans); 42 return 0; 43 }