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~728>
2~727=
2~835>
3~833>
4~830>
5~826<
5~935>
6~930>
7~924<
7~1034>
8~1027=
8~1138>
9~1130>
10~1121<
10~1233>
11~1223<
11~1336>
12~1325<
12~1439>
13~1427=
13~1542>
可以看出该方法本文章开头的算法节省了很多加法计算。



  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值