AtCoder Beginner Contest 169 B题,https://atcoder.jp/contests/abc169/tasks/abc169_b。
Given N integers A1,...,AN compute A1×...×AN.
However, if the result exceeds 10^18, print -1
instead.
Input is given from Standard Input in the following format:
N
A1 ... An
Print the value A1×...×AN as an integer, or -1
if the value exceeds 10^18.
2
1000000000 1000000000
1000000000000000000
We have 1000000000×1000000000=1000000000000000000.
3
101 9901 999999000001
-1
We have 101×9901×999999000001=1000000000000000001, which exceeds 10^18, so we should print -1
instead.
31
4 1 5 9 2 6 5 3 5 8 9 7 9 3 2 3 8 4 6 2 6 4 3 3 8 3 2 7 9 5 0
0
给了 N 个数,要求我们计算这 N 个数的乘积。但是这个乘积有个限制,如果乘积超过 10^18 这个数,我们就要输出 -1。
本题的难度不大。样例数据 1 和样例数据 2 没有什么需要分析的地方。我们要重点观察一下样例数据 3。
我们不难发现 已经超过了 10^18。但是题目给出的参考答案是 0。
也就是说,本样例数据是一个卡人的地方。就是说如果输入数据中有 0 存在,不管如何乘积的结果都不会超过 10^18。
所以本题不能直接读入数据累乘进行判断。
我们知道在 C++ 中,unsigned long long 的最大值是 2^64-1,也就是1.84*10^19。因此本题的难点在于如何判断两个数乘积超过了 unsigned long long 的范围,也就是数据越界。
判断两个数乘积是否超过数据的表示范围,我们可以用除法。假设两个数分别为 a 和 b,我们只需要用:最大值 / a 和 b 进行比较即可。如果 最大值 / a 小于 b,说明越界;否则不越界。
这个我们可以非常轻松的用一个简单数字来说明。如果 a 和 b 都是正数,而且 a*b 的值不能超过 10。那么当 a = 5 的时候,b 的取值范围只能是:0、1、2,这三个数。因此 10/5=2。
解决了这个判断,本题就很容易了。
1、读入 N 个数据。如果数据中有零,直接输出答案。
2、从第一个数据开始累乘,判断乘积是否会超过 unsigned long long 的表示范围或者超过 10^18。
#include
using namespace std;
const int MAXN = 2e5+2;
unsigned long long nums[MAXN];
const long long MAXL = 1e18;
//判断a*b是否超过1e18
bool overflow(unsigned long long a, unsigned long long b) {
//判断是否越界
if (ULLONG_MAX / a < b) {
return true;
}
//判断是否超过1e18
unsigned long long ans = a*b;
if (ans>MAXL) {
return true;
}
return false;
}
int main() {
int n;
scanf("%d", &n);
for (int i=0; i