0812 large a n mod p
ph
problem : for very large natural numbers \(a, n, p\), find the value of \(a^n \pmod{p}\).
Below process is finding the period. But it will appear to be unnecessary.
def a_exp_n_mod_p(a,n,p):
# `a` can be factorized. but it does not applied here, maybe it will make this much slower.
# Factorization is a very expensive process.
assert a > 0 and n > 0 and p > 0
if a%p ==0 :
return 0
# find the period.
# a^(2^n) has a period.
LIMIT = 10000 # period limit
x = [0]*LIMIT
anmodp = a%p
for i in range(LIMIT):
if anmodp in x:
x = x[:i]
for j in range(len(x)):
if x[j]==anmodp:
break
break
x[i] = anmodp
anmodp *= anmodp
anmodp %= p
assert len(x) < LIMIT
period_len = len(x)-j
#print period_len
#print len(x)
digit = 0
r = 1
while n>0:
if n%2 == 1:
r *= x[digit]
r %= p
n /= 2
digit += 1
if digit >= len(x):
digit -= period_len
assert digit >= 0
return r
assert a_exp_n_mod_p(3,20,20) == pow(3,20)%20
assert a_exp_n_mod_p(12,15,20) == pow(12,15)%20
assert a_exp_n_mod_p(12,15,19) == pow(12,15)%19
assert a_exp_n_mod_p(4,15,497) == pow(4,15)%497
print a_exp_n_mod_p(2032343532,24234234324,2342434234)
1368242842
As you can see, almost processes above is unnecessary.
Below is enough.
def anmodp2(a, n, p):
if n==1:
return a%p
tmp = anmodp2(a, n/2, p)
if n%2==1: #odd
return (a*(tmp**2))%p
else:
return (tmp**2)%p