PAT (Advanced Level) Practice
题目链接.
- 编程题 1065 A+B and C (64bit) (20分)
参考自《算法笔记》
Given three integers A, B and C in [−2^63 ,2^63 ], 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).
Sample Input:
3
1 2 3
2 3 4
9223372036854775807 -9223372036854775808 0
Sample Output:
Case #1: false
Case #2: true
Case #3: false
/*********************************************************************************************************************************/
思路:
由于 long long 的范围是 [-2^63, 2^63),因此题目中给出的两个整数相加有可能会溢出(正溢出或负溢出),直接进行大小判断会造成错误。在计算机组成原理中会指出,如果两个正数之和等于负数或是两个负数之和等于正数,那么就是溢出。对于溢出后的具体范围,可以进行如下分析:
- 当 A + B >= 2^63 时,显然有 A + B > C 成立,但 A + B 会因超过 long long 的正向最大值而发生正溢出。由于题目给定的 A 和 B 最大均为 2^63 - 1,故 A + B 最大为 2^64 - 2,因此使用 long long 存储正溢出后的值的区间为 [-2^63, -2](由(2^64 - 2) % (2^64) = -2 可得右边界 即去掉二进制数的第2^64位,剩下的就是溢出后剩下的数)。所以,当 A > 0, B > 0, A + B < 0 时为正溢出,输出 true.
- 当 A + B < -2^63 时,显然有 A + B < C 成立,但 A + B 会因超过 long long 的负向最小值而发生负溢出。由于题目给定的 A 和 B 最小均为 -2^63,故 A + B 最大为 -2^64,因此使用 long long 存储负溢出后的值的区间为 [0, 2^63 )(由(-2^64) % (2^64) = 0 可得左边界)。所以,当 A < 0, B < 0, A + B >= 0 时为负溢出,输出 false。
- 在没有溢出的情况下,当 A+B > C 时,输出 true;当 A + B <= C 时,输出 false。
注意点:
- 经测试,数据中并没有 A 或 B 取到 2^63 的情况,因此题目中的数据范围可能是写错了,应该是 [-2^63, 2^63) 才更符合数据,否则就要用带负数的大整数运算了(因为 long long 存储 2^63 时会自动变成 -2^63,无法区分左右边界)。
- A + B 必须存放到 long long 型变量中才可与 C 进行比较,而不可以在 if 的条件中直接相加与 C 比较,否则会造成后两组数据错误。
参考代码
#include <cstdio>
int main() {
int T, tcase = 1;
scanf ("%d", &T);
while (T--) {
long long a, b, c;
scanf ("%lld%lld%lld", &a, &b, &c);
long long res = a + b; //res 存放 a + b 的结果
bool flag;
if (a > 0 && b > 0 && res < 0) flag = true; //正溢出为 true
else if (a < 0 && b < 0 && res >= 0) flag = false; //负溢出为 false
else if (res > c) flag = true; //无溢出时,A + B > C 时为 true
else flag = false; //无溢出时,A + B <= C 时为 false
if (flag == true) {
printf ("Case #%d: true\n", tcase++);
} else {
printf ("Case #%d: false\n", tcase++);
}
}
return 0;
}