title: HDU-1001
categories:
- ACM
- 易错题
tags: - 大数陷阱
- 代数式最大化部分溢出
- 补码
- 计算机中运算过程
date: 2020-02-06 09:59:33
这个题的平均通过比率大约为0.25(20200206),平均提交四次才能通过。确实有一个大陷阱,这道题需要我们了解C语言的基本知识和计算机中的运算过程。
-
题目
Sum Problem
*Time Limit: 1000/500 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 677426 Accepted Submission(s): 170938
*Problem Description
Hey, welcome to HDOJ(Hangzhou Dianzi University Online Judge).
In this problem, your task is to calculate SUM(n) = 1 + 2 + 3 + … + n.
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.
扫描二维码关注公众号,回复: 9811872 查看本文章Sample Input
1 100
Sample Output
1 5050
C语言中IO和运算过程
例如cin>>a;
在屏幕上输入5然后点回车,存储过程为将5的补码存到a对应的地址,然后对这个补码进行运算。
例如2*a+1
先计算2*a
存到一个地方b,然后运算b+1。运算过程为一步一步的,每一步都保存结果,这样就导致了在运算过程中可能导致临时的结果溢出,例如本题中计算1+2+3+···+N有好多种算法(循环累加和公式法),我们都会下意识的用比较简单的n*(n+1)/2
,题目中告诉我们n*(n+1)/2
在有符号整形的范围之内,但是计算n*(n+1)
的时候要保存一个临时结果,这个结果是有可能比有符号整形大的,所以最终结果不准确。
解决方法
调整运算顺序将增大运算和减小运算交错排布
将n*(n+1)/2
调整为n/2*(n+1)
(n为偶数)或(n+1)/2*n
(n+1为偶数)
#include <stdio.h>
#include<iostream>
using namespace std;
int main(){
int a;
while(cin>>a){
if(a%2==0)
cout<<a/2*(a+1)<<endl<<endl;
else
cout<<(a+1)/2*a<<endl<<endl;
}
return 0;
}
消除运算过程中的减小运算(将公式法改为累加法)
#include <stdio.h>
#include<iostream>
using namespace std;
int main(){
int a;
while(cin>>a)
{
int sum=0;
for(int i=1;i<=a;i++)
sum+=i;
cout<<sum<<endl<<endl;
}
return 0;
}