bzoj4710 [Jsoi2011]分特產 容斥+組合數
阿新 • • 發佈:2019-02-03
Description
JYY 帶隊參加了若干場ACM/ICPC 比賽,帶回了許多土特產,要分給實驗室的同學們。
JYY 想知道,把這些特產分給N 個同學,一共有多少種不同的分法?當然,JYY 不希望任
何一個同學因為沒有拿到特產而感到失落,所以每個同學都必須至少分得一個特產。
例如,JYY 帶來了2 袋麻花和1 袋包子,分給A 和B 兩位同學,那麼共有4 種不同的
分配方法:
A:麻花,B:麻花、包子
A:麻花、麻花,B:包子
A:包子,B:麻花、麻花
A:麻花、包子,B:麻花
N, M 不超過1000,每一種特產的數量不超過1000
Output
輸出一行,不同分配方案的總數。由於輸出結果可能非常巨大,你只需要輸出最終結果
MOD 1,000,000,007 的數值就可以了。
Solution
每種至少有一個,那麼答案就是至少0個沒有的-至少1個沒有的+至少2個沒有的。。。
至少i個沒有的就是,等價於把a[j]個相同的球放進n-i個不同的盒子裡
Code
#include <stdio.h>
#include <string.h>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
const int MOD=1000000007;
const int N=20005 ;
int ny[N],fac[N];
int a[N];
int C(int n,int m) {
return 1LL*fac[n]*ny[m]%MOD*ny[n-m]%MOD;
}
int ksm(int x,int dep) {
int res=1;
for (;dep;dep>>=1) {
(dep&1)?(res=1LL*res*x%MOD):0;
x=1LL*x*x%MOD;
}
return res;
}
int main(void) {
fac[0]=1; rep(i,1,N-1) fac[i]=1LL*fac[i-1]*i%MOD;
rep(i,0,N-1) ny[i]=ksm(fac[i],MOD-2);
int n,m; scanf("%d%d",&n,&m);
rep(i,1,m) scanf("%d",&a[i]);
int ans=0;
rep(i,0,n-1) {
int tot=C(n,i);
rep(j,1,m) {
tot=1LL*tot*C(a[j]+n-i-1,n-i-1)%MOD;
}
if (i&1) ans=(ans-tot+MOD)%MOD;
else ans=(ans+tot)%MOD;
}
printf("%d\n", ans);
return 0;
}