整数划分

一.将n划分为小于m的划分数

1 划分的多个整数可以存在相同的

    dp[n][m] = dp[n][m-1]+dp[n-m][m]

 (1) 如果划分中的每个数都小于m,相当于dp[n][m] = dp[n][m-1] ,就是说将n划分为小于m的划分数 等于 将n划分为小于m-1的划分数

(2)如果划分中的存在一个数等于m,相当于dp[n][m] = dp[n-m][m],就是将划分中的m减去 ,求n-m的划分数

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdlib> 
using namespace std;
const int maxn = 1000;
int dp[maxn][maxn];
int main(){
	int n,m;
	cin>>n>>m;
	memset(dp,0,sizeof dp);
	for(int i = 1;i <= n;i++){
		dp[i][1]= i;
		dp[1][i] = 1;
		dp[0][i] = 1;
	}
	for(int i = 1;i <= n ;i++)
		for(int j = 1; j <= n;j++){
			if(j < i)
				dp[i][j] = dp[i][j-1] + dp[i-j][j];   
			else if(j == i)
				dp[i][j] = dp[i][j-1] + 1;    
			else
				dp[i][j] = dp[i][j-1];
		}
	cout<<dp[n][m]<<endl;
	return 0;
}

2.划分的多个整数不可以存在相同的

    dp[n][m] = dp[n][m-1] + dp[n-m][m-1]

(1) 如果划分中的每个数都小于m,相当于dp[n][m] = dp[n][m-1] ,就是说将n划分为小于m的划分数 等于 将n划分为小于m-1的划分数

 (2)    如果划分中的存在一个数等于m,相当于dp[n][m] = dp[n-m][m-1],因为这时候不能存在相同的,n减去m之后,就不会再存在等于m的划分,就是说所有的划分都小于m 

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdlib> 
using namespace std;
const int maxn = 1000;
int dp[maxn][maxn];
int main(){
	int n,m;
	cin>>n>>m;
	memset(dp,0,sizeof dp);
	for(int i = 1;i <= n;i++){
		dp[i][1]= i;
		dp[1][i] = 1;
		dp[0][i] = 1;
	}
	for(int i = 1;i <= n ;i++)
		for(int j = 1; j <= n;j++){
			if(j < i)
				dp[i][j] = dp[i][j-1] + dp[i-j][j-1];
			else if(j == i)
				dp[i][j] = dp[i][j-1] + 1;
			else
				dp[i][j] = dp[i][j-1];
		}
	cout<<dp[n][m]<<endl;
	return 0;
}
二.将n划分为k个正整数的划分数

  dp[n][k] = dp[n-k][k] +dp[n-1][k-1]

 (1)  如果划分的这k个正整数都是大于1的. dp[n][k] = dp[n-k][k] .就是将这k个正整数都减去1 ,它们的和就是m-k,就是相当于将n-k划分为k个正整数 

(2)如果划分的这k个正整数有一个等于1的,dp[n][k] = dp[n-1][k-1] . 就是将这k个划分中的1减去 ,然后就相当于将n-1划分为k-1个正整数

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdlib> 
using namespace std;
const int maxn = 1000;
int dp[maxn][maxn];
int main(){
	int n,m;
	cin>>n>>m;
	memset(dp,0,sizeof dp);
	for(int i = 1;i <= n;i++)
		dp[i][1]= 1;
	for(int i = 1;i <= n ;i++)
		for(int j = 1; j <= i;j++){
			if(j < i)
				dp[i][j] = dp[i-j][j] + dp[i-1][j-1];
			else if(j == i)
				dp[i][j] = 1;
		 
		}
	cout<<dp[n][m]<<endl;
	return 0;
}
三.将m划分为连续的正整数的划分数

例如 15的划分

15
7 ,8
4,5,6
1,2,3,4,5

将正整数m划分为连续的正整数,假设连续的最小值为x,划分的个数为i,那么     m = x*i + i*(i-1)/2 

划分的个数最多 为 x从1开始取值 ,如果i 是整数 ,就可以确定 划分的个数最多是 i,如果i不是整数 ,说明划分的个数比 i小

所以最大的划分数满足 i +i*(i-1)/2 <=m,  然后就可以根据划分数 i 来求的连续的最小值x,如果x为整数 ,说明划分数为i,最小值为x 是m的一种划分

#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
int split(const int m){
	int ans = 0;
	for(int i = 1; i+i*(i-1)/2 <= m;i++ ){
		int qt = m - i*(i-1)/2;
		int qc = qt%i;
		if(!qc){
			int x = qt/i;char ch;
			for(int j = 0;j < i;j++)
				printf("%d%c",x+j,j==i-1? ch = '\n':ch = ' ');
			ans++;
		}
	}
	return ans;
} 
int main(){
	int m;
	cin>>m;
	cout<<split(m)<<endl;
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值