Problem #97 concerns finding the last ten digits of a large Mersenne Prime. The question reads:
Project Euler Problem 97: Large non-Mersenne prime
The first known prime found to exceed one million digits was discovered in 1999, and is a Mersenne prime of the form 26972593−1; it contains exactly 2,098,960 digits. Subsequently other Mersenne primes, of the form 2p−1, have been found which contain more digits.
However, in 2004 there was found a massive non-Mersenne prime which contains 2,357,207 digits: 28433×27830457+1.
Find the last ten digits of this prime number.
My solution for this problem involves a famous algorithm known as the Exponentiation by squaring or square and multiply algorithm. Here is my solution:
Solution #1: Square and Multiply Approach
The problem is equivalent to finding the remainder when the given number is divided by 10^10. Clearly, it will leave a remainder of 1 when divided by 2^10. Thus, it suffices to find the remainder when it is divided by 5^10, as afterwards the Chinese Remainder Theorem (CRT) can be used to find a corresponding remainder mod 10^10. The Exponentiation by squaring algorithm allows us to find this remainder quickly. First, the exponent 7830457 is written in binary. (11101110111101110111001). This binary representation tells us which powers of 2 can be added to get the given exponent. With the well known fact that 2^a * 2^b = 2^(a+b), it follows that if we can find the remainder when powers of the form 2^(2^n) are divided by 5^10, we can multiply those powers according to the binary representation to get the remainder when 2^7830457 is divided by 5^10. Finally, we can multiply the result by 28433 and add 1 to get the remainder when the Mersenne Prime is divided by 5^10, and afterwards CRT can be used to get the last 10 digits. Here is an implementation of this approach in Python 2.7:
'''
Author: Walker Kroubalkian
Square and Multiply Approach to Project Euler Problem #97
'''
import time
def squareAndMultiply(b,e,m):
l = bin(e)[2:]
a = len(l)
exponents = []
myExponent = b
while(len(exponents)<a):
exponents.append(myExponent)
myExponent = (myExponent**2)%m
total = 1
c = l[::-1]
for x in range(a):
if(c[x] == '1'):
total*=exponents[x]
total%=m
return total
def projectEulerProblemNinetySeven(a,b,e,c,m):
return (a*squareAndMultiply(b, e, m) + c)%m
start = time.time()
print projectEulerProblemNinetySeven(28433, 2, 7830457, 1, 10**10)
print ("--- %s seconds ---" % (time.time()-start))
print bin(7830457)
'''
Prints
8739992577
--- 5.29289245605e-05 seconds ---
for input of a = 28433, b = 2, e = 7830457, c = 1, m = 10**10
'''
And with that, we’re done. The Square and Multiply approach is very common in computer science, so I may reuse this code in other problems.
Thanks for reading! See you tomorrow.


