acmcoder1001:Sum Problem细节问题

先来看看这个问题:

Input
The input will consist of a series of integers n, one integer per line.
Output
For each case, output SUM(n) in one line, followed by a blank line. You may assume the result will be in the range of 32-bit signed integer.
Sample Input
1
100
Sample Output
1

5050
当时一卡这个题目,觉得太简单了,可能常规做法就是用for循环累加,但是比较耗时,可以用数学神童高斯的公式来解决。然后很牛气的开始写起代码(牛气的是自己不仅想到了常规做法和他的缺点,还想到了优化方法,呵呵~这点出息……),代码如下:

<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!

心得:以后做题要看清题目,这是从小学老师开始就强调的问题!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值