Here we define gcd and fast exponentiation as functions:
def gcd(x, y): if y == 0: return x return gcd(y, x % y) def power(a, d, n): l = [] cur = d while cur != 0: l.append(cur % 2) cur = cur // 2 r = [] cur = a % n for i in range(len(l)): r.append(cur) cur = (cur ** 2) % n ans = 1 for i in range(len(l)): if l[i] == 0: continue ans = (ans * r[i]) % n return ans
Exercise 7.6.1
Find that satisfies:
n = 1111 for a in range(2, n): if gcd(a, n) != 1: continue if power(a, n-1, n) == 1: continue print(a) break
Result
2
Exercise 7.6.2
denotes the number of primes which are less than or equal to . Use Sieve of Eratosthenes.
n = 100 l = list(range(2, n+1)) for p in range(2, n+1): l = [i for i in l if i == p or i % p != 0] print(f'{len(l)}')
Result
25
Exercise 7.6.3
A pseudoprime to the base is an odd composite number which satisfies:
To check whether a certain number is prime or composite, Sieve of Eratosthenes is used.
max_n = 500 primes = list(range(2, max_n+1)) for p in range(2, max_n+1): primes = [i for i in primes if i == p or i % p != 0] a = 2 for n in range(2, max_n): if n in primes: continue if power(a, n-1, n) != 1: continue print(n) break
Result
341
Exercise 7.6.4
find that satisfies:
n = 2 ** (2 ** 5) + 1 for a in range(2, n): if gcd(a, n) != 1: continue if power(a, n-1, n) == 1: continue print(a) break
Result
3
Note:
Exercise 7.6.6
Introduce as the largest power of 2 which divides . Then we can define .
Find that satisfies:
where
n = 2 ** (2 ** 5) + 1 d = n - 1 s = 0 while d % 2 == 0: d = d // 2 s = s + 1 for a in range(2, n): if gcd(a, n) != 1: continue if power(a, d, n) == 1: continue flag = True for r in range(s): flag = flag and power(a, d*(2**r), n) != n - 1 if not flag: continue print(a) break
Result
3
Exercise 7.6.7
The pseudoprime is . Substitute 341 for in the above code, instead of .
Result
2
Exercise 7.6.8
Slightly changed.
n = 221 d = n - 1 s = 0 while d % 2 == 0: d = d // 2 s = s + 1 l = [] for a in range(2, n): if gcd(a, n) != 1: continue if power(a, d, n) == 1: continue # condition 2 flag = True for r in range(s): flag = flag and power(a, d*(2**r), n) != n - 1 if flag: l.append(a) print(len(l))
Result
186