CF451E Devu and Flowers
作者:互联网
De javu 和开花
咕了半个月没更博了(捂脸)
这题如果值域小显然可以背包,但是这题是\(n\)小值域大,\(20\)可以让人想到状压.分析一下又发现可以容斥,枚举哪些物品超过个数限制,设枚举集合为\(S\),然后每个物品都要用\(a_i+1\)个,那么这个集合的贡献为\((-1)^{|S|}\binom{s-(\sum a_i+1)+n-1}{n-1}\)
// luogu-judger-enable-o2
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<cmath>
#include<ctime>
#include<queue>
#include<map>
#include<set>
#define LL long long
#define db long double
using namespace std;
const int N=30,M=(1<<20)+10,mod=1e9+7;
LL rd()
{
LL x=0,w=1;char ch=0;
while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*w;
}
int n,nn,fac[N],iac[N],l2[M],fh[M];
LL s,a[N],b[M];
int fpow(int a,int b){int an=1;while(b){if(b&1) an=1ll*an*a%mod;a=1ll*a*a%mod,b>>=1;} return an;}
int inv(int a){return fpow(a,mod-2);}
int C(LL n,int m)
{
if(m<0||n<m) return 0;
LL xx=1;
for(int i=0;i<m;++i) xx=1ll*xx*(n%mod-i+mod)%mod;
return 1ll*xx*iac[m]%mod;
}
int cal(LL n,int m){return C(n+m-1,m-1);}
int main()
{
n=rd(),s=rd();
for(int i=1;i<=n;++i) a[i]=rd();
fac[0]=1;
for(int i=1;i<=n;++i) fac[i]=1ll*fac[i-1]*i%mod;
iac[n]=inv(fac[n]);
for(int i=n;i;--i) iac[i-1]=1ll*iac[i]*i%mod;
nn=1<<n;
for(int i=1;i<=n;++i) l2[1<<(i-1)]=i;
fh[0]=1;
for(int i=1;i<nn;++i) fh[i]=-fh[i^(i&(-i))],b[i]=b[i^(i&(-i))]+a[l2[i&(-i)]]+1;
int ans=0;
for(int i=0;i<nn;++i)
{
int dt=cal(s-b[i],n);
ans=(ans+(fh[i]==1?dt:mod-dt))%mod;
}
printf("%d\n",ans);
/*qwq*/
return 0;
}
标签:CF451E,Flowers,return,int,long,ch,Devu,include,define 来源: https://www.cnblogs.com/smyjr/p/10991773.html