AtCoder Beginner Contest 169 B I will explain the problem "Multiplication 2".
Problem URL: https://atcoder.jp/contests/abc169/tasks/abc169_b
A sequence of $ N $ integers ($ A_1, ..., A_N $) is given. $ A_1 × ... × A_N $, that is
\prod_{i=1}^{N} A_i
Ask for. However, if this value exceeds $ 10 ^ {18} $, output -1
.
・ $ 2 \ leq N \ leq 10 ^ 5 $ ・ $ 0 \ leq A_i \ leq 10 ^ {18} $ ・ All inputs are integers
This problem requires knowledge of multiple precision integers </ b>. If you enter the values of these sequences in ʻinttype and multiply them, <b> overflow will occur. </ b> Also, since the constraint is up to $ 10 ^ {18} $, <b> overflow will occur even if you input and multiply with
long int` type. </ b>
Therefore, we have to take some measures.
Sorting in descending order allows you to sort the sequence in descending order of numbers. Sorting the sequence has the same total product </ b>, so this is a good move.
After that, multiply the values in the sequence and output -1
when it exceeds </ b> $ 10 ^ {18} $ and end the process.
The amount of calculation is $ O (logN) $ for sorting and $ O (N) $ for multiplication, so it is $ O (NlogN) $.
Also, if you do not finish the process, it will be TLE </ font> in some languages. The reason is simple: multiplication of multiple-precision integers takes a long time to calculate.
For example, in Python3, C ++, Java, execute $ 100 × 100 $, $ 10 ^ 5 × 10 ^ 5 $, $ 10 ^ 9 × 10 ^ 9 $ multiplication, and $ 10 ^ {18} $ multiple times respectively. Let's compare the calculation time
(I used the code test of AtCoder)
(In Python3, I entered the value as ʻint, in C ++ as
long long int, and in Java, as
double` type and executed it.
( Calculation is based on the assumption that overflow will occur </ b>)
Calculation | Python3 | C++ | Java |
---|---|---|---|
18ms | 6ms | 122ms | |
21ms | 10ms | 106ms | |
18ms | 7ms | 122ms | |
19ms | 8ms | 122ms | |
18ms | 6ms | 118ms | |
585ms | 8ms | 113ms | |
10500ms | 9ms | 118ms |
As you can see, there is not much difference in calculation time between C ++ and Java, but with Python3, the execution time is limited due to the large number of calculations 2sec (2000ms) </ font> You can see that font> takes more calculation time.
If there is even one $ 0 $ in the sequence, the total product will naturally be $ 0 $, but if you do the same as Countermeasure 1, the sequence that includes $ 0 $ will actually output -1
. Will be done.
The reason is simple. This is because it is judged that the total product exceeds $ 10 ^ {18} $ due to the term with a large value that is not $ 0 $ by sorting, and it is output as -1
</ b>.
This causes the WA </ font> judgment to appear in the corner case such as zero_01.txt
.
So, when reading a sequence, let's create a flag function that sets $ 0 $ to 1 if it exists </ b>. Then you can determine if the total product is $ 0 $ before multiplying! </ B>
In Python3, you can check if the $ 0 $ term exists in ʻA.count (0)`.
In other words, the points of each language for this problem are as follows.
・ Python3 Multiplication of multiple-precision integers </ b> takes a lot of calculation time and should be avoided. ・ C ++, Java It is better to avoid calculation errors due to overflow </ b>
Below are examples of solutions in Python3, C ++, and Java.
{ABC169.py}
N = int(input())
A = list(map(int,input().split()))
A.sort()
A.reverse()
if A.count(0) > 0:
print(0)
else:
f = 0
ans = 1
for i in range(N):
ans *= A[i]
if ans > 10**18:
f += 1
print(-1)
break
if f == 0:
print(ans)
{ABC169.cpp}
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
cin >> n;
vector<long int> vec(n);
for (int i = 0; i < n; i++){
long int a;
cin >> a;
vec.at(i) = a;
if(vec.at(i) == 0){
cout << 0 << endl;
return 0;
}
}
sort(vec.begin(),vec.end());
reverse(vec.begin(),vec.end());
long int ans = 1;
for (int i = 0; i < n; i++){
if (vec.at(i) > 1000000000000000000/ans){
cout << -1 << endl;
return 0;
}else{
ans *= vec.at(i);
}
}
cout << ans << endl;
}
{ABC169.java}
import java.util.Scanner;
import java.util.Arrays;
public class Main{
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
long [] a = new long[n];
for (int i = 0; i < n; i++){
a[i] = scan.nextLong();
if (a[i] == 0){
System.out.println(0);
return;
}
}
Arrays.sort(a);
long ans = 1;
for (int i = n-1; i >= 0; i--){
if (a[i] > 1000000000000000000L/ans){
System.out.println(-1);
return;
}else{
ans *= a[i];
}
}
System.out.println(ans);
}
}
Recommended Posts