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

我的视频题解空间

posted on 2023-01-10 09:51  itdef  阅读(45)  评论(0编辑  收藏  举报

导航