- 题目
- 解题思路
- 解题代码
- 1. 错误解法
- 2. 正确解法(1)
- 3. 正确解法(2)
- 4. 正确解法(3)
- 5. 正确解法(4)
- 写在最后
解题思路循环输入,每输入一个正整数n(n ≤ 65535), 输出1 + 2 + 3 + … + n 的值,并且多输出一个空行。当没有任何输入时,结束 程序。
解题代码 1. 错误解法我们可以通过暴力枚举或者使用等差数列前n项和的公式来计算出来结果
# includeint main() { int n; while(scanf("%d",&n) != EOF) { int ans = n * (n + 1) / 2; printf("%dn",ans); } return 0; }
这里为什么出错了呢?逻辑是正确的呀?
2. 正确解法(1)这里的n是小于等于65535的,当n是65535的时候,那么n * (n + 1)已经溢出了,因为65535 可以看作是(216-1),那么可以自行计算一下n * (n + 1)的值,会大于int 所能表示的最大值231-1,所以这种方法没有考虑到溢出,所以会出错。
#includeint main() { int n = 1; while(scanf("%d",&n) != EOF) { int sum = 0;//(1) while(n) { sum += n; n--; } printf("%dn",sum); } return 0; }
- sum用于存放最后的相加得到的结果
#includeint main() { int n; int sum = 0; while(scanf("%d",&n) != EOF) { if (n % 2 == 0) //(1) { sum = n /2 * (n + 1); } else //(2) { sum = (n + 1) / 2 * n; } printf("%dn",sum); } return 0; }
- 如果输入的n是偶数的话,那么先计算等差数列求和公式中的n / 2,然后再乘(n + 1),这样将等差数列求和公式变一下形,那么我们就可以有效地避免错误解法中的n * (n + 1)这种溢出情况了。
- 如果输入的n是奇数的话,那么奇数加上一然后除以2,肯定得到的结果是偶数,那么我们也是将等差数列求和公式中的公式变一下形,从而有效地避免溢出。
4. 正确解法(3)总之,这里按照奇数和偶数分情况输出,是因为计算机中,计算除法是向下取整的,所以分奇偶情况来讨论的话,那么就不会因为计算机这种计算方法从而导致结果出错了。
由于边界溢出问题,所以我们才会考虑这么多的。那么我们扩大一下存储结果的范围,那么就不用这么辛苦地考虑边界溢出问题了。
由于C语言中有无符号整型这种数据类型,它的存储范围是[0.232-1],这个题目中最大的范围是n * (n + 1),可以自己手动计算一下,n * (n + 1)的范围是小于无符号整型的最大表示范围的,所以我们可以使用无符号整型来存放结果而不用担心溢出。
#includeint main() { int n; while( scanf("%d",&n) != EOF ) { unsigned int sum = 0; sum += n * (n + 1) / 2; printf("%un",sum);//(1) } return 0; }
- 由于这里使用了无符号整型,那么注意输出的格式应该是%u
我们可以考虑使用可以表示更大范围的数据类型来存储最后的结果,比如说这里使用 long long, long long 数据类型在C中可以表示的范围是: [- 263 , 263 -1],那么足以表示我们这道题目的结果了。
#includeint main() { int n; while( scanf("%d",&n) != EOF ) { long long sum = 0; sum = n * (n + 1) / 2; printf("%lldn",sum);//(1) } return 0; }
- 这里使用了 long long 数据类型,那么注意输出格式是%lld
由于该文章是读了CSDN博主英雄哪里出来后自己的一些总结,希望可以帮助到大家。英雄哪里出来的对应文章在这里:传送门。



