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;
}
作 者: itdef
欢迎转帖 请保持文本完整并注明出处
技术博客 http://www.cnblogs.com/itdef/
B站算法视频题解
https://space.bilibili.com/18508846
qq 151435887
gitee https://gitee.com/def/
欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
如果觉得不错,欢迎点赞,你的鼓励就是我的动力
欢迎转帖 请保持文本完整并注明出处
技术博客 http://www.cnblogs.com/itdef/
B站算法视频题解
https://space.bilibili.com/18508846
qq 151435887
gitee https://gitee.com/def/
欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
如果觉得不错,欢迎点赞,你的鼓励就是我的动力
![阿里打赏](https://files.cnblogs.com/files/itdef/ali2.bmp)
![微信打赏](https://files.cnblogs.com/files/itdef/weixin2.bmp)