整数划分

描述:将一个正整数n拆分成一组正整数连加并等于n的形式,而且这些连加的数中最大的加数不大于n。

正整数的划分数:上述划分所有可能的个数。

求正整数划分数的方法:

递归方法:

假设m为一种划分中的最大加数,如果m>n,则最大加数为n。

共分为四种情况讨论(其实可以看成三种):

  • 当n=1或m=1时,此时对正整数n只有一种划分方式,即当n=1时,划分为n=1; 当m=1时,n=1+1+...+1, 其中1的个数为n的大小。此时的划分数为1,用程序表示为 if(n==1||m==1) return 1;
  • 当m>n时,假设递归函数为int split(int n,int m),由于最大加数只能为n,此时可以等价于split(n,n),用程序可以表示为if(m>n) return split(n,n);
  • 当m=n时,可以用递归形式表示为split(n,m-1)+1,即包含加数为m的划分数加上最大加数为m-1的划分数,由于此时n=m,所以包含加数为m的划分数为1,用程序可以表示为if(m==n) return split(n,m-1)+1;
  • 当m<n时,这是最一般的情况,也是出现最多的情况。此时可以表示为split(n,m-1)+split(n-m,m),其中split(n-m,m)表示用最大加数为m的划分表示n-m。用程序表示为if(m<n) return split(n,m-1+split(n-m,m)。
C++源程序表述如下:

#include <iostream>
using namespace std;


int split(int n,int m)
{
    if(n<1||m<1) return 0;//invalid arguments
    if(n==1||m==1) return 1;
    if(m>n) return split(n,n);
    if(m==n) return split(n,m-1)+1;
    if(m<n) return split(n,m-1)+split(n-m,m);
}


int main()
{
    int split_number,add_number;
    cin>>split_number;
    cin>>add_number;
    cout<<split(split_number,add_number)<<endl;
    return 0;
}


另:将一个正整数划分为连续正整数之和,输出所有的可划分情况。

假设正整数为n,一个满足条件的划分中最小的正整数为x,那么这个划分可以表示为x+(x+1)+(x+2)+..+(x+m)=n,假设这个划分中整数的个数为y个,那么上式可以表示为(x*y)+y*(y-1)/2=n。

我们知道这样的划分中整数的个数可以为y个,那么y的最大值是多少呢?即一个划分中可以包含的连续整数的最大个数是多少呢?

假如一个划分从整数1开始,那么这个划分包含的整数个数将是最大的,由此可得y+y(y-1)/2=n => y(y+1)/2=n,  此即最大个数y应该满足的条件。

同样在确定y值的时候,可以根据式xy+y(y-1)/2=n来确定x的值,这个值就是连续整数中最小的整数值,当然若(n-y(y-1)/2)/y不是整数,那么就不能将整数n划分成包含y个的连续整数的和。

C++实现的划分函数如下:

int split(int n)
{
    int i, j, m = 0, x, t1, t2;
   // 在这里i + 1之所以变为i - 1,是因为i * (i - 1) / 2这个式子在下面多次用到,
  // 为了避免重复计算,因此将这个值计算完后保存在t1中。并且将<= 号变为了<号。
    for(i = 1; (t1 = i * (i - 1) / 2) < n; i++)
     {
         t2 = (n - t1);
         x =   t2 / i;
        if(x <= 0) break;
        if((n - t1) % i == 0)
         {
             cout<<x<<' ';
            for(j = 1; j < i; j++)
               cout<< x + j<<' ';
             cout<<endl;
             m++;
         }
     }
    return m;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值