女神的微笑---------------多重集的组合数,容斥原理

此题为多重集的组合数的 模板题  

根据容斥原理,暴力枚举所有子集合,并且算出当前子集合中的元素取法全为不合法的方案数。

然后根据容斥公式计算答案。

 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 }
代码
原文地址:https://www.cnblogs.com/wyher/p/9839536.html