将n个无区别的物品,划分成不超过m组,求划分方法数模M的余数
这样的划分称为n的m划分
dp[i][j] = j的i划分的总数
dp[i][j] = dp[i][j-i] + dp[i-1][j]
这个递推式可以不重复地计算所有的划分,复杂度为O(nm)
int dp[maxn][maxn];
void solve(){
dp[0][0] = 1;
for(int i = 1; i <= m; i++){
for(int j = 0; j <= n; j++){
if(j - i >= 0)
dp[i][j] = (dp[i-1][j] + dp[i][j-i]) % M;
else
dp[i][j] = dp[i-1][j];
}
}
cout << dp[m][n] << endl;
}
多重集组合数
n种物品,第i个物品有ai个。不同种类物品可以互相区分,相同种类物品无法区分。从这些物品中取出m个,有多少种取法?
dp[i+1][j] = dp[i+1][j-1] + dp[i][j] - dp[i][j-1-ai]
复杂度为O(nm)
int a[maxn];
int dp[maxn][maxn];
void solve(){
for(int i = 0; i <= n; i++)
dp[i][0] = 1;
for(int i = 0; i < n; i++){
for(int j = 1; j <= m; j++){
if(j - 1 - a[i] >= 0)
dp[i+1][j] = (dp[i+1][j-1] + dp[i][j] - dp[i][j-1-a[i]] + M) % M;
else
dp[i+1][j] = (dp[i+1][j-1] + dp[i][j]) % M;
}
}
cout << dp[n][m] << endl;
}