基本动态规划题学习笔记与解析——8(划分数问题)

这里我们仍然用dp来求解


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

样例输入
n=4
m=3
M=10000

输出
4 (1+1+2 = 1+3 = 2+2 = 4)

这样的划分被称作n的m划分数。 dp问题对于计算各种排列组合个数,概率或者期望之类的计算都非常有用,在此,我们定义如下数组

dp【i】【j】=j 的 i 划分的总数

根据这一关系,我们可以寻找到对应的递推式。 考虑n的m划分中 各项为 ai (1<=i<=m),如果对于每个i都有ai >0 ,那么所有ai 减1就对应了n-m 的m 划分.
另外 ,如果存在ai =0 ,那么其就对应相等于n的m-1 划分。综上,我们可以得到

dp【i】【j】=dp【i】【j-i 】+ dp【i-1】【j】;

可能上面描述有点简略难以理解,分享一下个人理解
所有的ai都是一样的,即可从某一个ai开始考虑,若ai不为零即
所有的ai都至少为2,将其减一后所有ai都至少唯一,这种情况下的化分数
相当于j-i的i划分,即为 dp【i】【j-i】
而当ai中存在1时,即建议后存在ai为零,这种情况下的划分可以视为某一个
ai不存在,即少了一段划分,即为dp【i-1】【j】,这两种情况包含所有情况,
将其加起来就是我们想要的解

代码如下

#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
int dp[100][100];
int main()
{
	int m,n,i,t,j,k,M;
	scanf("%d%d%d",&n,&m,&M);
	dp[0][0]=1;
	for(i=1;i<=m;i++)
	for(j=0;j<=n;j++)
	{
		if(j-i>=0)//当j
		{
			dp[i][j]=(dp[i-1][j]+dp[i][j-i])%M;
			/*所有的ai都是一样的,即可从某一个ai开始考虑,若ai不为零即
			所有的ai都至少为2,将其减一后所有ai都至少唯一,这种情况下的化分数
			相当于j-i的i划分,即为 dp【i】【j-i】
			而当ai中存在1时,即建议后存在ai为零,这种情况下的划分可以视为某一个
			ai不存在,即少了一段划分,即为dp【i-1】【j】,这两种情况包含所有情况,
			将其加起来就是我们想要的解*/
		}
		else//减少一个i看是否能划分
		{
			dp[i][j]=dp[i-1][j];
		}
	}
	printf("%d",dp[m][n]);
}

有问题欢迎和我一起交流!qwq

你可能感兴趣的:(萌新笔记,动态规划dp)