1. 题目描述
每次输入一个正整数n,计算 1+2+3+……+n 的和
- n的范围:n ≤ 65535
- 多组输入
错误的解法
我们没有编程经验的话,才开始学C语言,一般整形变量定义成 int,打印用%d,如果这样的话,这里就要踩坑了
#include <stdio.h>
int main()
{
int n;
while (scanf("%d", &n) != EOF)
{
printf("%d\n", n*(n + 1) / 2);//法一:前n项和公式
//存在问题:当 n 取最大值 65535 时,会溢出,不推荐使用
}
return 0;
}
为什么上面的代码不行呢?
当n取最大值65535的时候,n*(n+1) = 65535 * 65536 = (2^16-1) * 2^16 = 2^32 - 2^16,而int 类型的范围大小:- 2^31 ~ 2^31-1,所以如果用int类型的话,会产生溢出
正确解法一:枚举法
这是最不容易出错的,从1遍历到n,逐渐求和,然后打印,不过这样的时间复杂度就很高了O(N)
#include <stdio.h>
int main()
{
int n;
while(scanf("%d", &n) != EOF)//法一:循环遍历
{
int ret=0;
while(n)
{
ret+=n;
n--;
}
printf("%d\n\n",ret);
}
return 0;
}
正确解法二:奇偶判断法
奇数和:(n+1) / 2 * n 偶数和:n / 2 * (n+1)
#include <stdio.h>
int main()
{
int n = 0;
while (scanf("%d", &n) != EOF)//法二:奇偶判断法
{
int ret = 0;
if (n & 1)
{
ret = (n + 1) / 2 * n;
}
else
{
ret = n / 2 * (n + 1);
}
printf("%d\n\n", ret );
}
return 0;
}
正确解法三(对上面的错误代码进行修改)
第一版
#include <stdio.h>
int main()
{
unsigned int n = 0; // 用unsigned int 存,用%u打印
while (scanf("%d", &n) != EOF)
{
printf("%u\n", n*(n + 1) / 2); // 这里用%u打印
}
return 0;
}
第二版
#include <stdio.h>
int main()
{
long int n = 0; // 这里用 long int 存储,就不存在溢出了
while (scanf("%d", &n) != EOF)
{
printf("%d\n", n*(n + 1) / 2);
}
return 0;
}
总结
这个题目其实很简单,但是也会存在溢出问题影响结果的,所以在今后的编写代码过程中,要注意避免造成溢出。