杭电oj1001题
首先这是求和,我们有两种思路。
思路一:我们可以通过for循环进行n次累加,每次循环之后,变量加一。
如果代码这样写:
#include <stdio.h>
int main()
{
int a;
int sum=0;
while(scanf("%d",&a)!=EOF){
for(int i=0;i<=a;i++)
sum = sum+i;
printf("%d\n\n",sum);
}
return 0;
}
oj评判的是wrong answer
(出现wrong answer原因:
对于部分或者全部的测试数据都没有输出正确的结果
可以考虑:
算法的正确性和鲁棒性)
那么为什么sum置0要放while里呢?置0就要说到上篇文章杭电oj1000,写到分四种输入输出,这题也是第二种。所以它是输入一系列的数,会输出一系列的和,所以每次计算下一组时,就要在while里重置sum的值。
修改后的代码如下:
#include <stdio.h>
int main()
{
int a,sum;
while(scanf("%d",&a)!=EOF){
sum=0;
for(int i=0;i<=a;i++)
sum = sum+i;
printf("%d\n\n",sum);
}
return 0;
}
思路二:由数学基本知识,等差数列求和公式:首项加末项乘以项数除以2。
如果代码这样写:
#include<stdio.h>
int main()
{
int n,sum;
while(scanf("%d",&n)!=EOF)
{
sum=(n+1)*n/2;
printf("%d\n\n",sum);
}
return 0;
}
oj评判的是wrong answer
因此这里出现了乘法溢出的问题,在这里不能直接用等差数列求和公式,因为题中说:
You may assume the result will be in the range of 32-bit signed integer.
要求是求和之后的结果不能超过32位,
假设结果是一个32位的有符号整数,也就是说最大值是有符号整数范围要在-2的31次方到2的31次方-1之间,假设sum为2的31次方,那么根据sum=(n+1)*n/2可以大致得到n的大约取值是2的16次方,意味当n>=2的36次方就会溢出。对于部分测试数据会出错,所以前者无法通过测试。
也就是说,假设n*(n+1)/2的结果刚好满足32位。但是在做除法前n*(n+1)的结果就已经超过了32位。
若真的想用公式法,其实也可以,需要把除以2的运算拿到前面来,这样的话,就要判断一下输入是不是偶数了。
先判断奇偶,然后把n和n+1中偶数的一方除以二,再相乘,这样就不会溢出了。
修改后的代码:
#include<stdio.h>
int main()
{
int n,sum;
while(scanf("%d",&n)!=EOF)
{
if(n%2==0)
sum=n/2*(n+1);
else
sum=(n+1)/2*n;
printf("%d\n\n",sum);
}
return 0;
}
此外,注意一些小细节,控制一下格式。