递归求解一个正整数的不同划分数 个数,以及输出不同划分

将一个正整数N 划分为一系列的 正整数之和:

N = N1 + N2 + . . . + Nk;

其中,N1>=N2>=N3 .... >=Nk ,(k>=1) , 改表示称为 正整数N 的一个划分; 不同 划分方式 的种类个数成为划分数 。

例如: 将 N=3 划分:

3;

2+1;

1+1+1

在对正整数N 的所有划分中, 将最大加数N1 不大于M 的划分数记为 Q(N , M);

例如 对于 3 的划分中,我们定义 M=1, 则表示, 对于 3 的划分 最大加数 N1<=1 。

则可以建立如下的递归关系:  注下面的 n 为待划分的正整数N  , m 为 最大划分数 N1 

(1)当 n = 1   时 Q(n , m) = 1  只能划分成 1

(2)当 m = 1  时 Q(n , m) = 1 只能划分为 1

(3)当 n < m  时 Q(n , m) = Q(n , n) ,  例如 对于 3 的划分 , 将 M=4 ,它只会分成(3) (2+1) (1+1 +1) 

此次, 最大的划分数N1肯定 不会 超过 N 。

(4)当n = m 时  Q(n , m) = 1 + Q(n , n-1 ) ; 将问题分为两类 子问题, 即 最大划分数 为 n 的情况 和 n-1 的情况。

例如 n = m =3  , Q(3 , 3)  = 1 + Q(3, 2)  ,这里的 1  就是 最大划分数 N1=N =3  这种情况

(5)当 n> m 时  Q(n , m)  = Q(n, m-1) + Q(n-m , m)  ;如果 划正整数N 比 最大划分数N1大 的话, 我们可以按照 m-1 划分, 剩下的部分 按照 m 划分 。 直接进行 m 划分 的, 或许会造成 n-m 部分中含有 不小于 m  的部分。所以 我现 进行 m-1 划分, 在对 剩下的部分 进行 m 划分, 如此 划分下去, 我就可以保证 所有的划分数中 最大划分数 不大于 m .

例如 n=4, m= 2  ; Q(5 , 2 ) =  Q(5,1) + Q( 3 , 2) ; 其中 Q(5 , 1) =1 ;  对于 Q(3 , 2) = Q(3 , 1) + Q(1 , 2) ;  所以 Q(5, 2) =  3 .

//当  n=1 , m=1  时 是能 分成 1                                                                 所以 q(1,1)=1
//当  n<m         时 即为不大于 n 的划分  即 q(n,n)   ,                                          所以 n<m  时   q(n,m) = q(n,n)
//当  n=m         时 情况 1 : 划分为 n  , 情况2 划分为 不大于 n-1 ,即 q(n,n-1) ,  所以         所以 n=m  时   q(n,m) = 1 + q(n,n-1)
//当  n>m         时 情况 1  :按照不大于 m-1,情况2(剩下的 n-m 有可能大于 m),所以将剩下的数在按照 不大于 m 划分(也即总划分中包含m 的情况)   所以 n>m  q(n,m)= q(n,m-1) + q(n-m,m);

//求出一个数n 不大于 m  的划分数
#include<iostream>
#include<cstdio>
using namespace std;
int Q(int n,int m)
{
    if(n==1||m==1)
        return 1;
    if(n<m)
    return Q(n,n);
    if(n==m)
    return 1+Q(n,n-1);
    if(n>m&&m>1)
    return Q(n,m-1)+Q(n-m,m);
}
int  main()
{
    int n,m;
    cin>>n>>m;
    cout<<Q(n,m);
    return 0;
}

递归输出一个正整数N 的不同 划分数:

例如 :正整数N=3的不同划分:

3

2+1

1 + 1 +1 

 

#include<iostream>
#include<cstdio>
using namespace std;
int mak[300];
int n;
void Integer_Divide(int now_n,int k,int pre)
{
    if(now_n>n)
        return ;
    if(now_n==n)
    {
      cout<<n<<" = ";
        for(int i=0;i<k-1;i++)
           cout<<mak[i]<<"+";
        cout<<mak[k-1]<<endl;
    }
    else
    {
        for(int j=pre;j>=1;j--){
            mak[k]=j;
            now_n+=j;
            Integer_Divide(now_n,k+1,j);
            now_n-=j;//恢复现场
        }
    }
}
int main()
{
cin>>n;
Integer_Divide(0,0,n);
}

 

 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值