This is the code I'm using for calculating (n^p)%mod
. Unfortunately, it fails for large values of mod
(in my case mod = 10000000000ULL
) when I call it from main()
method. Any idea; why?
ull powMod(ull n, ull p, ull mod) {
ull ans = 1;
n = n%mod;
while(p) {
if(p%2 == 1) {
ans = (ans*n)%mod;
}
n = (n*n)%mod;
p /= 2;
}
return ans;
}
Here, ull
is a typedef for unsigned long long
.
One of the possible issues here seems to be that when you do
(a*b)%c
, thea*b
part itself could overflow, resulting in a wrong answer. One way to work around that is to use the identity thatis equivalent to
This will prevent overflows in the intermediate multiplications as well.
It seems that you can't avoid it.
If
mod
is10000000000ULL
, in(a*b)%c
in your program, botha
andb
are smaller than mod so we treat them as9999999999ULL
,a*b
will be99999999980000000001
, butunsigned long long
can only express2^64-1=18446744073709551615 < 99999999980000000001
so your method will be overflow.Yes you can do it in C++. As others pointed out you cannot do it directly. Using a little drop of number theory it is possible to decompose the problem into two manageable sub problems.
First consider that
10^10 = 2^10 * 5^10
. Both factors are coprime, so you can use the Chinese remainder theorem to find the power modulo10^10
using the powers modulo2^10
and modulo5^10
.Note that in the following code the magic values
u2
andu5
were found using the Extended Euclidean Algorithm. You don't need to program this algorithm yourself because these values are constants. I use maxima and its gcdex function, to compute them.Here is the modified version:
Your code line
is repeatedly executed. As long as n is smaller than mod, this will potentially result in evaluating (mod-1)*(mod-1) at some point in time.
On input n may not be so large, but the mentioned line of code increases n in the loop.