NOI 2.7 7219:复杂的整数划分问题

题目来源:http://noi.openjudge.cn/ch0207/7219/

7219:复杂的整数划分问题

总时间限制200ms  内存限制65536kB

描述

将正整数表示成一系列正整数之和,n=n1+n2+…+nk, 其中n1>=n2>=…>=nk>=1 k>=1 
正整数的这种表示称为正整数的划分。

输入

标准的输入包含若干组测试数据。每组测试数据是一行输入数据,包括两个整数N K 
(0 < N <= 50, 0 < K <= N)

输出

对于每组测试数据,输出以下三行数据:
第一行: N划分成K个正整数之和的划分数目
第二行: N划分成若干个不同正整数之和的划分数目
第三行: N划分成若干个奇正整数之和的划分数目

样例输入

5 2

样例输出

2
3
3

提示

第一行:4+1, 3+2,
第二行: 54+13+2
第三行: 51+1+3 1+1+1+1+1+1

-----------------------------------------------------

解题思路

动态规划

1. k个正整数和

dp[i][j]: i的j个正整数划分数, dp[i][j] =dp[i-j][j]+dp[i-1][j-1]

dp[i-j][j]: i-j的j个正整数划分上每个正整数+1;

dp[i-1][j-1]: i-1的j-1个正整数划分再添上一个1

// 超级巧妙的思路哇~

2. 不同整数和

dp[i][j](1<=j<=i): 整数i的这样的划分数,其中每个划分得到的最大整数为j

dp[1][1] = 1

dp[i][j] =sum(dp[i-j][k]), 2<=kwhenj

dp[i][j] = 1,                       when i==j

3. 正奇数和

dp[i][j]: 正整数i的这样的划分数,使得每个划分中最大的正奇数为j

dp[i][j] =dp[i-j][k], 1<=k<=j, k是正奇数

// 2. 和 3. 都是在NOI 2.7 7215:简单的整数划分问题的基础上的一点小改动

// 2. 就是求和的时候k必须小于j,不能等于j,且k要从2开始遍历

// 3.  就是j、k都是奇数

-----------------------------------------------------

代码

// 动态规划
// 1. k个正整数和
// dp[i][j]: i的j个正整数划分数, dp[i][j] = dp[i-j][j]+dp[i-1][j-1]
// dp[i-j][j]: i-j的j个正整数划分上每个正整数+1; 
// dp[i-1][j-1]: i-1的j-1个正整数划分再添上一个1
// 2. 不同整数和
// dp[i][j] (1<=j<=i): 整数i的这样的划分数,其中每个划分得到的最大整数为j
// dp[1][1] = 1
// dp[i][j] = sum(dp[i-j][k]), 2<=k
#include
using namespace std;

const int NMAX = 55;
int dp[NMAX][NMAX] = {};

void clearDP()								// 清零dp数组
{
	int i;
	for (i=0; i> n >> k)
	{
		if (n==1)
		{
			cout << 1 << endl << 1 << endl << 1 << endl;
			continue;
		}

		ans2 = 0;
		ans3 = 0;
		// 1. k个正整数和
		clearDP();
		dp[1][1] = 1;
		for (i1=2; i1<=n; i1++)
		{
			for (i2=1; i2<=k; i2++)
			{
				if (i2<=i1)
				{
					dp[i1][i2] = dp[i1-i2][i2] + dp[i1-1][i2-1];
				}
			}
		}
		cout << dp[n][k] << endl;
		// 2. 不同的正整数和
		clearDP();
		dp[1][1] = 1;
		for (i1 = 2; i1 <= n; i1++)
		{
			for (i2 = 2; i2


你可能感兴趣的:(noi,Cpp,动态规划,正整数划分,基础算法,NOI)