将整数分解为连续自然数之和

将一个正整数,拆分成连续的自然数之和,输出所有可能的情况

例如: 3 = 1+2

        10 = 1+2+3+4

        18 = 5+6+7

偶然见到这个问题,这里写下自己的解法。

分析:

对给定整数x以及一组满足要求的数字序列:a1a2......an,有

x=a1+a2+......an

数字的序列可以看做是一个公差为1的等差数列,数列的和根据数列的性质,可以得出满足要求的序列的一些性质。

数列的和即x可以数列的一项或两项来表示:

n为偶数时,x=(ai+aj)*n/2;i+j=n+1    (1)

n为奇数时,x=n*ak;k=n/2+1            (2)

1.从中可知,若n为奇数,则x一定可以被n整除,而这n个数字中间的一个就是x/n,并且可以据此得出这个数左右各(n-1)/2个数字。

若n为偶数,则(1)中的i和j可以取特定的两个值n/2、n/+1;ai和aj是相邻的两个数字,则有ai+aj是奇数,x/n=(ai+aj)/2,则有x不能被n整除,而2x可以被n整除。对于任一对i+j=n+1都有ai+aj,取i=1,j=n,可以解出a1,再依次加一得到序列的其他数字。

2.对于长度一定为n的连续自然数串,和最小的序列应该是1,2......n,和为n(n+1)/2,如果x<这个值,就说明不可能会有长度超过n的数串之和为x。

即应该满足:n(n+1)/2<=x →n^2<2x

由以上内容可以写出伪代码如下:

decompose(x):

n=1

while(n*n<2x) 

do

      if(n%2==1&&x%n==0) 有该长度数字序列

      if(n%2==0&&2x%n==0&&x%n!=0) 有该长度数字序列

      n++

done

c代码:

void decompose(int num)
{
//序列的长度
int i=1;
int k=0;
//序列第一个数字
int aFirst;


printf("%d:\n",num);

while(i*i<2*num)
{
if(i%2==1)
{
if(num%i==0)
{
aFirst=num/i-i/2;
                for(k=0;k                     printf("%d ",(k+aFirst));
}
                printf("\n");
}
}
        else
{
if((2*num)%i==0&&num%i!=0)
{
aFirst=num/i-(i/2)+1;
                for(k = 0;k {
                    printf("%d ",k+aFirst);
}
                printf("\n");
}
}

        i++;  
}
}


你可能感兴趣的:(算法,c)