I got this question yesterday in a challenge. I thought I had coded it correctly and my sample test case was passed. However not even a single test case passed at the backend. Here is my code. Please, someone, help me out. The challenge is over for me and so I can't submit it further. But I want to learn from my mistakes. Thanks.
import java.io.*;
//import java.util.*;
public class TestClass {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
PrintWriter wr = new PrintWriter(System.out);
int n = Integer.parseInt(br.readLine().trim());
String[] arr_a = br.readLine().split(" ");
int[] a = new int[n];
for(int i_a=0; i_a<arr_a.length; i_a++)
{
a[i_a] = Integer.parseInt(arr_a[i_a]);
}
long out_ = solve(a);
System.out.println(out_);
wr.close();
br.close();
}
static long solve(int[] a){
// Write your code here
long sum = 0l;
long MAX = 10000000011l;
long i = 1l;
for(int x : a) {
long count = 0;
while(x>0) {
x &= (x-1l);
count++;
}
long res = 1l;
long temp = i;
count = count % MAX;
while(temp > 0) {
if((temp & 1l) == 1l) {
res = (res * count) % MAX;
}
temp = temp >> 1l;
count = ((count % MAX) * (count % MAX)) % MAX;
}
long t =((sum%MAX) + (res % MAX))%MAX;
sum = t;
i++;
}
return sum;
}
}
It is a bit strange that "not even a single test case passed", but the only error I see is your exponentiation by squaring part.
All your numbers are less than 10^10 + 11
, but this constant has more than 32 bits, and when you multiply, you get an overflow sometimes (because long
is a 64-bit signed integer).
This can be fixed by several approaches:
(a*b) % M
operation can be done with the algorithm that is similar to your "exponentiation by squaring" implementation. You just need to replace all multiplications with additions. As a result, multiplication is replaced with O(log(n))
additions and 'multiplying by 2' operations. Sample implementation:
static long multiply(long a, long b, long M) {
long res = 0;
long d = a % M;
while (b > 0) {
if ((b & 1) == 1) {
res = (res + d) % M;
}
b >>= 1;
d = (d + d) % M;
}
return res;
}
You can just cache b^i % M
numbers for previously computed steps. For every number of set bits (there are not so many of them), you can save previously computed values and last(b)
- the last i
when a[i]
had b
set bits. Then just compute the new value with a linear loop from last(b) + 1
till current index i
.
Use BigInteger for multiplications.