This question actually comes from a Competitive Programming site called codechef.
The question is as follow.
Given integers A, B and N, you should calculate the GCD of A^N+B^N and |A−B|. (Assume that GCD(0,a)=a for any positive integer a). Since this number could be very large, compute it modulo 1000000007 (109+7).
The complete question is here
Constraints on values are as follow :
1 <= A,B,N <= 1e9 (Sub task #1)
1 <= A,B,N <= 1e12 (Sub task #2)
B <= A always
My Solution passes the first Subtask but Fails on Second when Values of A, B, N are very large.
Here is my solution :
#include <bitset>
#include <iostream>
using std::bitset;
using std::cin;
using std::cout;
typedef unsigned long long ull;
constexpr size_t bit_size = sizeof(ull) * 8;
ull modular_exponetiation(ull a, bitset<bit_size> n, ull mod) {
ull c = 0;
ull d = 1;
for (int t = n.size() - 1; t >= 0; t--) {
c *= 2;
d = ((d % mod) * (d % mod)) % mod; //(d*d)%mod
if (n[t] == 1) {
c++;
d = ((d % mod) * (a % mod)) % mod; //(d*a)%mod
}
}
return d;
}
ull euclid_gcd(ull a, ull b) {
if (b == 0)
return a;
else
return euclid_gcd(b, a % b);
}
int main() {
int test;
cin >> test;
while (test--) {
ull a, b, n;
cin >> a >> b >> n;
ull modder = a - b;
if (modder != 0) {
ull out_res = 0;
bitset<bit_size> bin_rip(n);
ull first_mod_res = (modular_exponetiation(a, bin_rip, modder) +
modular_exponetiation(b, bin_rip, modder)) %
modder;
if (first_mod_res == 0)
out_res = modder;
else
out_res = euclid_gcd(modder, first_mod_res);
cout << out_res % 1000000007 << std::endl;
} else {
// mod by 0 is not defined using the problem defined result.
// GCD(0,a) == a;
ull modder = 1000000007;
bitset<bit_size> bin_rip(n);
ull res = (modular_exponetiation(a, bin_rip, modder) +
modular_exponetiation(b, bin_rip, modder)) %
modder;
cout << res << std::endl;
}
}
return 0;
}
Request
It is not a Homework nor I want a precise answer or code correction. I do understand all these but cannot understand why would it fail on larger values?
Any direction or hint would be useful.