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