如果一个正整数可以由连续正整数求和而来,输出所有可能的组合

在写《判断一个正整数是否可以由连续正整数求和而来》的过程中,看到很多正整数n,可以用不止一组的连续正整数求和而来,如9=2+3+4=4+5,那么怎么求得所有符合要求的区间呢?我还是使用《判断一个正整数是否可以由连续正整数求和而来》提到的模拟法,只是在找到一个符合要求的区间之后,并不返回,而是强制它向右滑动,继续搜索可能的区间。注意搜索只在[1,n]的前半段(即[1,(n+1)/2])进行,因为后半段任意两个数的和都大于n。看代码:

View Code
 1 #include <iostream>
 2 using namespace std;
 3 
 4 //模拟法
 5 //用一个在数轴上的正整数区间,来模拟求解过程。
 6 //具体来说,如果区间内整数的和小于n,则区间右边界向右移动,如果区间内整数的和大于n,则区间左边界向右移动,如果区间内整数的和等于n,则n可以由区间内的整数求和表示,程序终止。
 7 //如果想要找到所有符合要求的区间,那么在找到一个符合要求的区间之后,并不返回,而是强制它向右滑动,继续搜索可能的区间。
 8 //注意搜索只在[1,n]的前半段(即[1,(n+1)/2])进行,因为后半段任意两个数的和都大于n。
 9 int valid(int n){
10     if(n<=1) {
11         cout<<n<<"="<<n<<endl;
12         return 0;
13     }
14     int first=1;//区间左边界
15     int last=1;//区间右边界
16     int sum=1;//区间内整数的和
17     int count=0;//count统计所有可能的区间个数
18     do{
19         //n>sum, 则区间右边界向右移动
20         if(n>sum)    {
21             last++;
22             sum+=last;
23         }
24         //n<sum, 则区间左边界向右移动
25         else if(n<sum) {
26             sum-=first;
27             first++;
28         }
29         //n==sum
30         else{
31             //输出结果
32             count++;
33             cout<<n<<"=";
34             for(int i=first;i<last;i++)
35                 cout<<i<<"+";
36             cout<<last<<endl;
37             //强制区间向右滑动
38             sum-=first;
39             first++;
40         }
41     }
42     while(last<=(n+1)/2); //搜索只在[1,(n+1)/2]进行
43     if(count==0)
44     {
45         cout<<n<<"="<<n<<endl;
46         return 0;
47     }
48     else
49         return count;
50 }
51 
52 int main()
53 {
54     int n=105;
55     cout<<n<<"共有"<<valid(n)<<"种表示方法。"<<endl;
56     system("pause");
57     return 0;
58 }

n=sum([k1,k2])


实际上也可以用数学分析法解决这个问题,涉及到因式分解和解方程组,比较麻烦,有兴趣的朋友可以自己试试。不足之处,欢迎交流。

原文地址:https://www.cnblogs.com/emituofo/p/2770402.html