[PAT Advanced Level] 1065 A+B and C
题目
Given three integers A, B and C in [ − 2 63 , 2 63 ] [-2^{63},2^{63}] [−263,263] , you are supposed to tell whether A+B>C.
Input Specification:
The first line of the input gives the positive number of test cases, T (≤10). Then T test cases follow, each consists of a single line containing three integers A, B and C, separated by single spaces.
Output Specification:
For each test case, output in one line Case #X: true if A+B>C, or Case #X: false otherwise, where X is the case number (starting from 1).
提供A,B,C三个整数,判断A+B是否大于C,共提供T组。
输入,第一行为T,接下来依次是每组的A,B,C。
输出, Case #X: true; Case #X: false
示例
输入:
3
1 2 3
2 3 4
9223372036854775807 -9223372036854775808 0
输出:
Case #1: false
Case #2: true
Case #3: false
题解
本题的关键,在于大数溢出的处理和判断。
由于long long的范围是 [ − 2 63 , 2 63 ) [-2^{63},2^{63}) [−263,263),那么两个整数相加时可能会出现正溢出或负溢出。计算机组成原理指出,如果两个正数之和等于负数或两个负数之和等于正数,那就是溢出。
- A + B ≥ 2 63 A+B\geq 2^{63} A+B≥263,A+B因超过long long 的正向最大值而正溢出,A+B的溢出范围为 [ 2 63 , 2 64 − 2 ] [2^{63},2^{64}-2] [263,264−2],结果为 [ − 2 63 , − 2 ] [-2^{63},-2] [−263,−2],res为负。
- A + B ≤ − 2 63 A+B\leq -2^{63} A+B≤−263,A+B因超过long long 的负向最大值而负溢出,A+B的溢出范围为 [ − 2 64 , − 2 63 ] [-2^{64},-2^{63}] [−264,−263],结果为 [ 0 , 2 63 ] [0,2^{63}] [0,263],res为正。
因此考虑到溢出,需要再加一个判断条件res,long long res=a+b;。
关于溢出
如果位数为w的两个数x,y,且为补码形式表示。
- 2 w − 1 ≤ x + y < 2 w − 1 2^{w-1} \leq x+y < 2^{w-1} 2w−1≤x+y<2w−1,结果正常
- x + y < − 2 w − 1 x+y < -2^{w-1} x+y<−2w−1,负溢出,结果为 x + y + 2 w x+y+2^w x+y+2w
- x + y ≥ 2 w − 1 x+y \geq 2^{w-1} x+y≥2w−1,正溢出,结果为 x + y − 2 w x+y-2^w x+y−2w
#include<cstdio>
int main()
{
int T,tcase=1;
long long a,b,c;
scanf("%d",&T);
for(int i=0;i<T;i++)
{
scanf("%lld%lld%lld",&a,&b,&c);
long long res=a+b;
bool flag;
if(a>0&&b>0&&res<0) flag=true; //正溢出
else if(a<0&&b<0&&res>=0) flag=false; //负溢出
else if(res>c) flag=true; //无溢出,A+B>C
else flag=false; //无溢出,A+B<=C
if(flag) printf("Case #%d: true\n",i+1);
else printf("Case #%d: false\n",i+1);
}
return 0;
}
参考
[算法笔记-上机训练实战指南-胡凡]