地址 https://www.papamelon.com/problem/224
有 n 個無區別的物品, 將它們劃分成不超過 m 組,求劃分方法數模 M 的餘數
輸入
輸入第一行有三個整數 n、m、M
1≤m≤n≤1000
1≤M≤10^4
輸出
輸出一個整數表示劃分方法數模 M 的餘數
樣例 1
輸入
4 3 10000
輸出
4
解答
先從簡單模型觀察 然後向已有模型上套
4個物品分成3堆 可以分成004 013 022 112
問題可以轉化爲 3個數字 相加爲4 可以有幾種方案
允許出現0 並且爲了避免 400 004這些相同的分配答案出現 我們規定數字排列從小到大
現在的問題描述變爲 m個數字 相加爲n 可以有幾種方案, 方案數字排列從小到大.
dp[m][n]表示 m個數字相加爲n的方案數
dp[m][n]可以分成兩部分 所有數字不爲0的情況下
112 -> 001 3個數字 相加爲4的不出現0的方案數 ,其實就是每個數字上減1的那種組合的方案數,即 3個數字相加爲1的方案數,也就是dp[m][n-m]
所有數字有0的情況
004->04 3個數字 相加爲4的不出現0的方案數 ,其實就是固定一個數字爲0後的那種組合的方案數,即2個數字相加爲4的方案數 也就是dp[m-1][n]
013->13
022->22
狀態轉換
dp[m][n] = dp[m][n-m]+dp[m-1][n]
代碼如下
#include <iostream>
using namespace std;
const int N = 1010;
int dp[N][N];
int n, m, M;
int main()
{
cin >> n >> m >> M;
dp[0][0] = 1;
for (int i = 1; i <= m; i++) {
for (int j = 0; j <= n; j++) {
dp[i][j] += dp[i - 1][j];
if (j >= i) {
dp[i][j] += dp[i][j - i];
}
dp[i][j] %= M;
}
}
cout << dp[m][n] << endl;
return 0;
}