52 lines
1.1 KiB
Python
52 lines
1.1 KiB
Python
from lib_prime import primes
|
|
from functools import cache
|
|
from math import gcd
|
|
|
|
|
|
def get_phi_table(n: int, ps: list[int]) -> list[int]:
|
|
tbl = [-1] * (n + 2)
|
|
tbl[1] = 1
|
|
queue = [(1, 1, 0)]
|
|
|
|
while queue:
|
|
x, phi, pi = queue.pop()
|
|
for pin in range(pi, len(ps)):
|
|
p = ps[pin]
|
|
tbl[p] = p - 1
|
|
xn = x * p
|
|
if xn > n:
|
|
break
|
|
d = gcd(x, p)
|
|
phid = tbl[d]
|
|
assert phid != -1
|
|
phin = (phi * (p - 1) * d) // phid
|
|
tbl[xn] = phin
|
|
queue.append((xn, phin, pin))
|
|
return tbl
|
|
|
|
|
|
def euler_214():
|
|
n = 40 * 10**6
|
|
ps = primes(n)
|
|
tbl = get_phi_table(n, ps)
|
|
|
|
@cache
|
|
def chain(n: int) -> int:
|
|
if n == 1:
|
|
return 1
|
|
n = tbl[n]
|
|
return 1 + chain(n)
|
|
|
|
s = 0
|
|
for i in range(len(ps)):
|
|
p = ps[i]
|
|
if chain(p) == 25:
|
|
s += p
|
|
return s
|
|
|
|
|
|
if __name__ == "__main__":
|
|
solution = euler_214()
|
|
print(f"e214.py: {solution}")
|
|
assert solution == 1677366278943
|