当时一卡这个题目,觉得太简单了,可能常规做法就是用for循环累加,但是比较耗时,可以用数学神童高斯的公式来解决。然后很牛气的开始写起代码(牛气的是自己不仅想到了常规做法和他的缺点,还想到了优化方法,呵呵~这点出息……),代码如下:
提交之后,却发现结果是wrong answer。顿时懵了,这么简单的代码都会错,之后再看原题,有这么一句:You may assume the result will be in the range of 32-bit signed integer.原来问题出在这里,计算结果都存在32位的int里,这也包括中间结果:(1+n)*n/2。也就是说在计算过程中发生了溢出,恍然大悟!接下来思考该怎么解决:
<span style="font-size:18px;">#include <iostream>
using namespace std;
int main()
{
int n;
while(cin>>n)
{
cout<<(1+n)*n/2<<endl<<endl;
}
return 0;
}</span>
提交之后,却发现结果是wrong answer。顿时懵了,这么简单的代码都会错,之后再看原题,有这么一句:You may assume the result will be in the range of 32-bit signed integer.原来问题出在这里,计算结果都存在32位的int里,这也包括中间结果:(1+n)*n/2。也就是说在计算过程中发生了溢出,恍然大悟!接下来思考该怎么解决:
方案一:使用老方法,for循环累加;
方案二:既然是中间计算结果发生溢出,那就找出中间计算公式,看能不能改成不溢出。首先看公式(1+n)*n/2,先做乘法运算后作除法运算,乘法是发生溢出的罪魁祸首,然而除法不可能发生溢出(如果是在汇编中,也会溢出)。那么就可以考虑先做除法,先将中间结果变小就行了。但是做除法还要考虑的就是要小心类型的隐式转换:如果是奇数作除法,结果会有偏差,因为题设是中间结果保存在int型变量中。一次可以将输出作如下改进:
cout<<((n%2==0)?n/2*(1+n):(1+n)/2*n)<<endl<<endl;
提交代码,Accept!
心得:以后做题要看清题目,这是从小学老师开始就强调的问题!