算法分析经典例题——整数划分:

题目描述:

将正整数n表示成一系列正整数之和:n=n1+n2+…+nk,其中n1≥n2≥…≥nk≥1,k≥1。
正整数n的这种表示称为正整数n的划分。求正整数n的不同划分个数。
例如:正整数6有如下11种不同的划分:
6;
5+1;
4+2,4+1+1;
3+3,3+2+1,3+1+1+1;
2+2+2,2+2+1+1,2+1+1+1+1;
1+1+1+1+1+1。

一些经典的递归问题(阶乘,斐波那契),问题本身都具有比较明显的递归关系,

因而容易用递归函数直接求解。

在本例中,如果设p(n)为正整数n的划分数,则难以找到递归关系,因此考虑增加

一个自变量:将最大加数n1不大于m的划分个数记作q(n,m)。可以建立q(n,m)的如

下递归关系。(若不理解加粗部分,建议把题目多读几遍)

(1) q(n,1)=1, n≥1; 当最大加数n1不大于1时,任何正整数n只有一种划分形式,

即n=1+1+…+1(n个1)

(2) q(n,m)=q(n,n), m ≥ n;
最大加数n1实际上不能大于n。因此,q(1,m)=1。

(3) q(n,n)=1+q(n,n-1);
正整数n的划分由n1=n的划分和n1 ≤ n-1的划分组成。

(4) q(n,m)=q(n,m-1)+q(n-m,m), n>m> 1;
正整数n的最大加数n1不大于m的划分,由n1≤ m-1 的划分和n1=m的划分组成。

n1=m 的划分就是该划分中必然包含数m,因此其划分的数目与n-m的m划分一致。

如果设p(n)为正整数n的划分数,则难以找到递归关系,因此考虑增加一个自变量:

将最大加数n1不大于m的划分个数记作q(n,m)。可以建立q(n,m)的如下递归关系。

(正整数n的划分数p(n)=q(n,n)。 )

 

代码实现:

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

const int N = 2e5+100;

int sol(int n,int m) {
    //状态转移不是很明白怎么回事。。。
	if(n==1||m==1)return 1;
	else if(n<m)return sol(n,n);
	else if(n==m)return 1+sol(n,m-1);
	else return sol(n,m-1)+sol(n-m,m);
	//1<m<n
}

int main() {
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF) {
        printf("%d\n",sol(n,m));
    }
    return 0;
}

THE END;

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值