[JSOI2011]分特产
题目大意:
有n个人,m种物品,第i种物品有a[i]个。
现在给这些人发物品,要求每个人至少发到一件物品。
问有多少种不同的发法。
思路:
首先不考虑“每个人至少发到一件物品”的限制,那么答案应该是$\prod\binom{n-1+a[j]}{n-1}$。
考虑容斥,答案为都取的方案数-1个人不取的方案数+2个人不取的方案数...都不取的方案数。
假设有i个人不取,那么方案数就是$\prod\binom{n-i-1+a[j]}{n-i-1}$。
最后加减几次即可。
1 #include<cstdio> 2 #include<cctype> 3 typedef long long int64; 4 inline int getint() { 5 register char ch; 6 while(!isdigit(ch=getchar())); 7 register int x=ch^'0'; 8 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); 9 return x; 10 } 11 const int N=1000,M=1000,mod=1e9+7; 12 int a[M],c[N<<1][N<<1]; 13 int main() { 14 const int n=getint(),m=getint(); 15 for(register int i=0;i<m;i++) { 16 a[i]=getint(); 17 } 18 for(register int i=0;i<n<<1;i++) { 19 c[i][0]=1; 20 for(register int j=1;j<=i;j++) { 21 c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod; 22 } 23 } 24 int ans=0; 25 for(register int i=0;i<=n;i++) { 26 int tmp=c[n][i]; 27 for(register int j=0;j<m;j++) { 28 tmp=(int64)tmp*c[n-i-1+a[j]][n-i-1]%mod; 29 } 30 tmp*=i&1?-1:1; 31 ans=((ans+tmp)%mod+mod)%mod; 32 } 33 printf("%d\n",ans); 34 return 0; 35 }