划分数

问题描述

有n个无区别的物品,将它们划分成不超过m组,求出划分方法数模M的余数

限制条件

1 <= m <= n <= 1000

2 <= m <= 10000

声明 将n 分成m 堆 这样称作 n的m划分

定义dp[i][j] i 的 j划分的个数

递推过程

考虑n的m划分ai(a0 +a1 + ... + am = an) > 0

那么{ai-1}就对应着n-m 的 m 划分

如果有ai = 0 那么就对应了n 的 m-1划分

所以dp[i][j] = dp[i-j][j] + dp[i][j-1]

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 using namespace std;
 5
 6 int n, m, M;
 7 int dp[1007][1007];
 8 int main()
 9 {
10     freopen("in.txt", "r", stdin);
11     scanf("%d%d%d", &n, &m, &M);//n划分为不超过 m堆
12     memset(dp, 0, sizeof(dp));
13     dp[0][0] = 1;//0分到0堆 个数为1
14     //dp[i][j] --->>> j的i划分
15     for (int i = 1; i <= m; i++)
16     {
17         for (int j = 0; j <= n; j++)
18         {
19             if (j - i >= 0) dp[i][j] = dp[i-1][j] + dp[i][j-i];
20             else dp[i][j] = dp[i-1][j];
21         }
22     }
23     cout << dp[m][n] << endl;
24     return 0;
25 }
时间: 2024-12-18 00:48:41

划分数的相关文章

划分数系列问题

整数划分 --- 一个老生长谈的问题: 1) 练练组合数学能力. 2) 练练递归思想 3) 练练DP 总之是一道经典的不能再经典的题目: 这道好题求: 1. 将n划分成若干正整数之和的划分数. 2. 将n划分成k个正整数之和的划分数. 3. 将n划分成最大数不超过k的划分数. 4. 将n划分成若干奇正整数之和的划分数. 5. 将n划分成若干不同整数之和的划分数. 1.将n划分成不大于m的划分法: 1).若是划分多个整数可以存在相同的:  dp[n][m]= dp[n][m-1]+ dp[n-m]

最容易理解的划分数算法

这是划分数的常见解法 上面的解法我完全没有理解,怎么都没有理解怎么会想到这样去做递归,智商太低没办法. 但是没有关系,我还是绞尽脑汁想到了一种方法,即使常见的构建回溯树的方式.虽然消耗了些多余的空间,但是也算不错,代码简单有用. 当求 4的划分数时我是这样构建树的:(在只是画了两层,如下的树我们则可以用来遍历求和,如果和等于 4则划分数 +1) public class HuaFen{ public int num; //需要划分的个数 //n表示需要划分的值, m表示迭代到的层数,count表

NYOJ 571 —— 各种划分数

整数划分(三) 时间限制:1000 ms  |  内存限制:65535 KB 描述 整数划分是一个经典的问题.请写一个程序,完成以下要求. 输入 每组输入是两个整数n和k.(1 <= n <= 50, 1 <= k <= n) 输出 对于输入的 n,k;第一行: 将n划分成若干正整数之和的划分数.第二行: 将n划分成k个正整数之和的划分数.第三行: 将n划分成最大数不超过k的划分数.第四行: 将n划分成若干个 奇正整数之和的划分数.第五行: 将n划分成若干不同整数之和的划分数.第六

编程算法 - 划分数 代码(C)

划分数 代码(C) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 有n个无区别的物品, 将它们划分成不超过m组, 求出划分方法数模M的余数. 例如: n=4的m=3个划分, result=4(1,1,2; 1,3; 2,2; 4) 使用动态规划(DP)方法, n的m划分a, 如果每个i都有a, {a-1}的集合就是n-m的m划分; a=0时, 就是n的m-1划分. 递推公式: dp[i][j] = dp[i][j-i] + dp[i-1][j] 代码

挑战程序设计竞赛 划分数,贝尔数,斯特灵数

斯特灵数:把n个数划分为恰好k个非空集合的个数,记为S(n,k).且有:S(n,1)=S(n,n)=1. 有递推关系式: S(n+1,k)=S(n,k?1)+kS(n,k?1) 贝儿数:把n个数划分为非空集合的所有划分数.有: Bn=∑i=0nS(n,i) 贝尔数的递推公式: Bn=∑k=0n(nk)Bk 书上的划分数:书上求的是:把n个相同的数划分为不超过m个集合的方法总数.由于这n个数是相同的,就不能算作∑ki=0S(n,i).书上给了这样一个dp的转移方程(定义dp[i][j]为j个数的i

计数DP(划分数,多重集组合数)

划分数:把n个无区别的物品划分成不超过m组. dp[i][j]=j的i划分的总数. dp[i[j]=dp[i][j-i]+dp[i-1][j] 即:将j个物品分成i份,有两种情况:每份划分都大于等于1 dp[i][j-i]; 存在有一份以上用0划分dp[i-1][j] int main() { int n,m; cin>>n>>m; dp[0][0]=1; for(int i=1;i<=n;i++) for(int j=0;j<=n;j++) { if(j>=i)

划分数 (DP)

输入: n=4 m=3 M=10000 输出: 4 (1+1+2=1+3=2+2=4) 复杂度(nm) 1 int n,m; 2 int a[MAX]; 3 4 int dp[MAX][MAX]; //数组 5 6 void solve() 7 { 8 dp[0][0]=1; 9 for(int i=0; i<=m; i++){ 10 for(int j=0; j<=n; j++){ 11 if(j-i >= 0){ 12 dp[i][j]=(dp[i-1][j]+dp[i][j-i])

hdu1028 划分数

题意是将一个整数N划分成不超过N个整数的和, 我们定义d[i][j]为j划分成不超过i个整数的和的方案数, 那么d[i][j] = d[i][j-i](全大于0) + d[i-1][j](不全大于0). 答案就是d[N][N], 代码如下: #include <iostream> #include <algorithm> using namespace std; typedef long long LL; LL d[150][150]; int main() { d[0][0] =

hdu 5119 (类似于划分数的状态定义) (DP中的计数问题)

题目描述:求n个数中异或值大于m的方案数有多少个? 设状态f[i][j]代表前i个数异或值为j的方案数有f[i][j]种,那么对于j来说要么选第i个数与前面的i-1个数中的某些数构成j,f[i-1][j^a[i]]],要么不选第i个数,直接由前面的i-1个数构成j,f[i-1][j];  f[i][j]=f[i-1][j^a[i]] + f[i-1][j] ; 注意到j的取值范围为10^6约等于2^(20),所以n个数亦或的最大值最多为20个1. 亦或的特性 : 任何数与0相亦或不变 ,任何数与