224. 劃分數(挑戰程序設計競賽)

地址 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;
}

我的視頻題解空間

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章