廢話不多說,反正小w要發喜糖啦!!
小w一共買了n塊喜糖,發給了n個人,每個喜糖有乙個種類。這時,小w突發奇想,如果這n個人相互交換手中的糖,那會有多少種方案使得每個人手中的糖的種類都與原來不同。
兩個方案不同當且僅當,存在乙個人,他手中的糖的種類在兩個方案中不一樣。
第一行,乙個整數n
接下來n行,每行乙個整數,第i個整數ai表示開始時第i個人手中的糖的種類
對於所有資料,1≤ai≤k,k<=n,n<=2000
一行,乙個整數ans,表示方案數模100000000961
1223
310題解:顯然我們應該將每種糖果放在一起處理,用v[i]表示有多少人有第i種糖果。然後考慮容斥,用f[i][j]表示前i種糖果,至多j個人的糖果與原來不同的方案數,然後很容易dp求出f陣列。
$f[i][j]=\sum\limits_^f[i-1][j-k]*c_^*(v[i])*(v[i]-1)*...*(v[i]-k+1)$
發現我們在dp過程中並沒有考慮我們選出來那j個人的順序,所以最後f[i][j]乘上j!即可。最後因為每個糖果是相同的,所以方案數要除以v[i]!。
#include #include #include #include using namespace std;typedef long long ll;
const ll p=1000000009;
int n,m;
ll ans;
int col[2010],s[2010],v[2010];
ll c[2010][2010],f[2010][2010],jc[2010],ine[2010],jcc[2010];
inline int rd()
while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
return ret*f;
}int main()
jc[0]=ine[0]=jcc[0]=jc[1]=ine[1]=jcc[1]=1;
for(i=2;i<=n;i++)
for(i=1;i<=n;i++) col[i]=rd();
sort(col+1,col+n+1);
for(i=1;i<=n;i++)
for(i=1;i<=m;i++) s[i]=s[i-1]+v[i];
f[0][0]=1;
for(i=1;i<=m;i++) for(j=0;j<=s[i-1];j++) for(k=0;k<=v[i];k++)
f[i][j+k]=(f[i][j+k]+f[i-1][j]*c[v[i]][k]%p*jc[v[i]]%p*jcc[v[i]-k]%p)%p;
for(i=0;i<=n;i++)
for(i=1;i<=m;i++) ans=ans*jcc[v[i]]%p;
printf("%lld",ans);
return 0;
}
BZOJ 4665 小w的喜糖 dp,容斥
qwq做的第一發這種題 f i j 表示分配了前i種,至少有j個人不合法,然後容斥一下就好 最後統計的時候,剩下的n j個人的分配方法是 n j 除以每種糖剩餘數量的階乘的積,這個積直接在dp的時候算好 include define mod 1000000009 define maxn 2005 u...
bzoj4665 小w的喜糖(dp 容斥)
time limit 10 sec memory limit 128 mb submit 222 solved 130 submit status discuss 廢話不多說,反正小w要發喜糖啦!小w一共買了n塊喜糖,發給了n個人,每個喜糖有乙個種類。這時,小w突發奇想,如果這n個人相互交換手中的糖...
BZOJ4665 小w的喜糖
考慮列舉哪些人一定不合法,那麼方案數可以通過簡單的排列組合算出。於是設 f i j 表示前 i 種糖果,一共有 j 個人一定不合法的方案數,但是這樣並不能保證其他人一定合法,所以需要進行容斥。最後將答案除以每種糖果數量的階乘,即可保證本質不同。時間複雜度 o n 2 includeconst int...