zoukankan      html  css  js  c++  java
  • [算法]正整数分解为几个连续自然数之和

    题目:输入一个正整数,若该数能用几个连续正整数之和表示,则输出所有可能的正整数序列。

    一个正整数有可能可以被表示为n(n>=2)个连续正整数之和,如:
    15=1+2+3+4+5
    15=4+5+6
    15=7+8

    有些数可以写成连续N(>1)个自然数之和,比如14=2+3+4+5;有些不能,比如8.那么如何判断一个数是否可以写成连续N个自然数之和呢?

    一个数M若可以写成以a开头的连续n个自然数之和,则M=a+(a+1)+(a+2)+…+(a+n-1)=n*a+n*(n-1)/2,要求a!=0,否则就是以a+1开头的连续n-1个整数了,也就是要求(M-n*(n-1)/2)%n==0,这样就很容易判断一个数可不可以写成连续n个自然数的形式了,遍历n=2…sqrt(M)*2,还可以输出所有解。

    copycode

    void divide(int num)  
    {  
        int i,j,a;  
        for(i=2; i<=sqrt((float)num)*2; ++i)  
        {  
            if((num-i*(i-1)/2)%i==0)  
            {  
                a=(num-i*(i-1)/2)/i;  
                if(a>0)  
                {  
                    for(j=0; j<i; ++j)  
                        cout<<a+j<<" ";  
                }  
                cout<<endl;  
            }  
        }   
    }  

    copycode[1]

    第二个问题是什么样的数可以写成连续n个自然数之和,什么样的数不能?

    通过编程实验发现,除了2^n以外,其余所有数都可以写成该形式。下面说明为什么。
    若数M符合条件,则有M=a+(a+1)+(a+2)+…+(a+n-1)=(2*a+n-1)*n/2,而2*a+n-1与n肯定一个为奇数一个为偶数,即M一定要有一个奇数因子,而所有2^n都没有奇数因子,因此肯定不符合条件。
    再证明只有M有一个奇数因子,即M!=2^n,M就可以写成连续n个自然数之和。假设M有一个奇数因子a,则M=a*b。

    1. 若b也是奇数,只要b-(a-1)/2>0,M就可以写成以b-(a-1)/2开头的连续a个自然数;将这条结论里的a和b调换,仍然成立。15=3*5=1+2+3+4+5=4+5+6.
    2. 若b是偶数,则我们有一个奇数a和一个偶数b。
    • 2.1 若b-(a-1)/2>0,M就可以写成以b-(a-1)/2开头的连续a个自然数。24=3*8=7+8+9.
    • 2.2 若(a+1)/2-b>0,M就可以写成以(a+1)/2-b开头的连续2*b个自然数。38=19*2=8+9+10+11.

    上述两个不等式必然至少有一个成立,所以可以证明,只要M有一个奇数因子,就一定可以写成连续n个自然数之和。

    另一个正整数分解的算法:
    sum(i,j)为i累加到j的和 
    令 i=1 j=2 
    if sum(i,j)>N i++ 
    else if sum(i,j)<N j++ 
    else cout i...j

    参考代码:

    copycode[2]

    #include <iostream>   
    using namespace std;  
      
    int add(int m,int n)  
    {  
        int sum=0;  
        for(int i=m;i<=n;i++)  
            sum+=i;  
        return sum;  
    }  
      
    void divide(int num)  
    {  
        int i=1,j=2,flag;  
        int sum=0;  
        while(i<=num/2)  
        {  
         sum=add(i,j);  
         while(sum!=num)  
         {  
            if(sum>num)  
                i++;  
            else  
                j++;  
            sum=add(i,j);  
         }  
         for(int k=i;k<=j;k++)  
            cout<<k<<" ";  
         ++i;  
         cout<<endl;  
        }  
    }  
      
    int main()  
    {  
        int num;  
        cout<<"Please input your number:"<<endl;  
        cin>>num;  
        divide(num);  
        return 0;  
    }  

    copycode[3]

  • 相关阅读:
    产品需求说明书PRD模版
    会编程的 AI + 会修 Bug 的 AI,等于什么 ?
    会编程的 AI + 会修 Bug 的 AI,等于什么 ?
    会编程的 AI + 会修 Bug 的 AI,等于什么 ?
    luogu P1164 小A点菜
    luogu P1347 排序
    luogu P1195 口袋的天空
    luogu P1182 数列分段Section II
    luogu P1332 血色先锋队
    luogu P1983 车站分级
  • 原文地址:https://www.cnblogs.com/wangyaning/p/4262843.html
Copyright © 2011-2022 走看看