1. 程式人生 > >[BZOJ4710][Jsoi2011]分特產(容斥原理+組合數學)

[BZOJ4710][Jsoi2011]分特產(容斥原理+組合數學)

題目描述

傳送門

題解

這道題的限制其實挺不明顯的,應該是“每個人都至少有一個”
也就是說對於所有的物品,將其劃分成n部分,每部分不能為空,問總的方案數
可以如果利用插板法的話,把n個相同的小球放到m個不同的盒子裡有Cm1n+m1種方案,不過這個只能求出允許空的方案數,對每一種特產都討論的話,總方案數即為iCn1ai+n1
根據容斥原理,答案應該為至少0個盒子為空的-至少1個盒子為空的+至少2個盒子為空的-…至少n個盒子為空的
那麼我們可以每一次強制i個盒子為空,剩餘的再像上面一樣選就行了

程式碼

#include<algorithm>
#include<iostream>
#include<cstring> #include<cstdio> #include<cmath> using namespace std; #define Mod 1000000007 #define LL long long int n,m,a[1005],c[2005][2005]; LL ans; int main() { for (int i=0;i<=2000;++i) c[i][0]=1; for (int i=1;i<=2000;++i) for (int j=1;j<=2000;++j) c[i][j]=(c[i-1
][j]+c[i-1][j-1])%Mod; scanf("%d%d",&n,&m); for (int i=1;i<=m;++i) scanf("%d",&a[i]); for (int i=0,f=1;i<=n;++i,f=-f) { LL now=1; for (int j=1;j<=m;++j) now=now*c[a[j]+n-i-1][n-i-1]%Mod; ans=(ans+now*c[n][i]%Mod*f)%Mod; } ans=(ans%Mod
+Mod)%Mod; printf("%lld\n",ans); }