2.16 連續整數的固定和 C實現
該問題出自《C語言名題精選百則技巧篇》
題目:編寫一個程式,讀入一個正整數,把所有那些連續的和為給定正整數的正整數找出來,例如,如果輸入27,發現2~7,8~10,13~14的和是27,這就是解答。如果輸入的是10000,應該有18~142,297~328,388~412,1998~2002這4組,注意不見得一定有答案,比如,4、16就無解,另外排除只有一個數的情況,否則每一個輸入就都至少有一個答案,就是它自己。
不費腦筋的演算法就是,設定兩個變數i個j,令j>i,i從1到n/2,j從i+1到n/2+1,因為從i到j必須是連續的,並且i+j<=n,只有在j=i+1的情況下會有可能會發生i+j=n,如果i>n/2,j>i>n/2,因此i+j>n。因此i<=n/2;如果j>n/2+1,如果i = j-1>n/2, i+j>n。因此j<n/2+1。設定兩個for迴圈,將i到j的數相加,判斷和是否等於給定的數GIVEN。這樣做的問題當然可以找到i和j,但是當GIVEN數值特別大的時候,這種方法非常的浪費時間。
這種方法的程式碼為:
for(i=1;i<=n/2;i++)
for(sum=i,j=i+1;j<=n/2+1;j++){
sum+=j;
if(sum == n)
printf("\n%ld ~ %ld",i,j);
}
我們可以考慮以下幾點:
(1)用i+(i+1)+...+(j-1)+j來表示,那麼i<=n/2。上面已經證明過。
(2)如果某個和i+(i+1)+...+(j-1)+j比給定值GIVEN大,那麼要把和變小,但是仍然要維持遺傳連續的整數,拿掉j變成i+(i+1)+...+(j-1),不如拿掉i變成 (i+1)+...+(j-1)+j,拿掉j下降太快,不如拿掉i,再慢慢降低;
(3)如果 i+(i+1)+...+(j-1)+j比給定值GIVEN小,加上j+1變成i+(i+1)+...+(j-1)+j+(j+1)。
本文所採用的解法如下:
(1) 先求出一個和,sum=1+2+...+j; 並且sum是第一個大於等於給定值GIVEN的和,例如,GIVEN=27,那麼sum就是1+2+...+7 = 28. j=7作為j的初值
(2) 若和sum = i+(i+1)+...+(j-1)+j比給定值GIVEN大,就把和去掉最小的那一端,變成sum = sum -i = (i+1)+...+(j-1)+j;如果和sum
= i+(i+1)+...+(j-1)+j 比給定值GIVEN小,就讓sum = sum +(j+1) 變成i+(i+1)+...+(j-1)+j
+(j+1); 如果等於GIVEN,就把i和j顯示出來。
(3)以上步驟反覆執行,直到i>n/2為止。
程式如下:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
long left,right;
long sum;
long GIVEN;
int count =0;
printf("\nConsecutive sum to a fix given number");
printf("\n=====================================");
printf("\nPlease input a Given number--->");
scanf("%ld",&GIVEN);
for(sum = 0,right=1;sum<GIVEN;sum+=right,right++);
for(left=1,right--;left<=GIVEN/2;){
if(sum > GIVEN){
sum -= left;
left++;
}else{
if(sum == GIVEN){
printf("\n%ld = sum from %ld to %ld",GIVEN,left,right);
count ++;
}
sum += (++right);
}
}
if(count>0)
printf("\n\nThrer are %d solutions in total.",count);
else
printf("\n\nSorry,threr is no solution at all.");
while(1)
getchar();
return 0;
}
執行結果:
執行過程:
i~j | 和 | 比較結果 |
1~7 | 28 | > |
2~7 | 27 | = |
2~8 | 35 | > |
3~8 | 33 | > |
4~8 | 30 | > |
5~8 | 26 | < |
5~9 | 35 | > |
6~9 | 30 | > |
7~9 | 24 | < |
7~10 | 34 | > |
8~10 | 27 | = |
8~11 | 38 | > |
9~11 | 30 | > |
10~11 | 21 | < |
10~12 | 33 | > |
11~12 | 23 | < |
11~13 | 36 | > |
12~13 | 25 | < |
12~14 | 39 | > |
13~14 | 27 | = |
13~15 | 42 | > |