在写《判断一个正整数是否可以由连续正整数求和而来》的过程中,看到很多正整数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 }
实际上也可以用数学分析法解决这个问题,涉及到因式分解和解方程组,比较麻烦,有兴趣的朋友可以自己试试。不足之处,欢迎交流。