转自:http://www.blker.com/?p=745
问题:
将正整数拆分为连续自然数之和
公式:
连续的自然数之和让我们想到了等差数列求和公式:
注:其中Sum为要分解的正整数,n为连续自然数的个数,aFirst为连续自然数的第一位数
将以上公式改写成另外一种格式
注:求解得到连续自然数个数n:
如果一个数可以分解为几个连续自然数之和,那么就意味着方程有解,那么对于相应的解就有如下限制,
必须为平方数且开根号的结果必须为奇数
需要注意的:由于是连续自然数,所以首项aFirst必定不可能大于n/2,所以不需要从1-n遍历,只需要从1- n/2 遍历即可。
01 | // partitionSum.cpp : Defines the entry point for the console application. |
02 | // |
03 |
04 | #include "stdafx.h" |
05 | #include <math.h> |
06 |
07 | int main( int argc, char * argv[]) |
08 | { |
09 | // 等差数列求和公式 Sum = n*aFirst + n*(n-2)/2; |
10 | // Sum 为要拆分的整数, |
11 | // n 为拆分后连续自然数个数 |
12 | // aFirst 为连续自然数中的第一位数 |
13 |
14 | int Sum, aFirst; |
15 | int i,j; |
16 | int w,k,m; |
17 | printf ( "请输入要分解的自然数Sum: " ); |
18 | scanf ( "%d" ,&Sum); |
19 | printf ( "/n" ); |
20 |
21 | for (i = 1; i <= Sum/2; i++) //由于是连续自然数,所以首项必定不可能大于n/2 |
22 | { |
23 | aFirst = i; |
24 | w = (2*aFirst-1) * (2*aFirst-1) + 8*Sum; |
25 | k = ( int ) sqrt (w); |
26 | m = k - 2*aFirst + 1; |
27 | if (k*k != w) // k是一个平方数 |
28 | continue ; |
29 | else if (m %2 !=0) // m必须为偶数 |
30 | continue ; |
31 | else |
32 | { |
33 | printf ( "可以分解%d个连续自然数:/n" ,m/2); |
34 | for (j=1;j<=m/2;j++) |
35 | printf ( "%d " ,i+j-1); |
36 | printf ( "/n/n" ); |
37 | } |
38 | } |
39 |
40 | return 0; |
41 | } |
效果如下: