""" A unit fraction contains 1in the numerator. The decimal representation of the unit fractions with denominators 2 to 10 are given: 1/2 = 0.5 1/3 = 0.(3) 1/4 = 0.25 1/5 = 0.2 1/6 = 0.1(6) 1/7 = 0.(142857) 1/8 = 0.125 1/9 = 0.(1) 1/10 = 0.1 Where 0.1(6) means 0.166666..., and has a 1-digit recurring cycle. It can be seen that 1/7 has a 6-digit recurring cycle. Find the value of d < 1000 for which 1/d contains the longest recurring cycle in its decimal fraction part. """ import random import time def timer(func): def wrapper(*args, **kwargs): start_time = time.time() result = func(*args, **kwargs) end_time = time.time() print(f"{func.__name__} took {end_time - start_time:.6f} seconds") return result return wrapper def repeating_cycle_fermat(d: int) -> int: # 移除因子2和5 while d % 2 == 0: d //= 2 while d % 5 == 0: d //= 5 if d == 1: return 0 # 费马小定理:对于与10互质的d,10^(φ(d)) ≡ 1 mod d # 循环节长度一定是φ(d)的约数 # 计算欧拉函数φ(d) phi = d n = d # 质因数分解求φ(d) p = 2 while p * p <= n: if n % p == 0: phi -= phi // p while n % p == 0: n //= p p += 1 if p == 2 else 2 # 从2开始,然后检查奇数 if n > 1: phi -= phi // n # 现在找φ的最小约数k,使得10^k ≡ 1 mod d min_cycle = phi for k in range(1, int(phi**0.5) + 1): if phi % k == 0: if pow(10, k, d) == 1: return k other = phi // k if pow(10, other, d) == 1 and other < min_cycle: min_cycle = other return min_cycle @timer def main_searchall(n: int) -> None: max_cycle = 0 max_d = 0 for d in range(1, n): cycle = repeating_cycle_fermat(d) if cycle > max_cycle: max_cycle = cycle max_d = d print(f"{max_d} have {max_cycle} digits in its decimal fraction part.") def is_probable_prime(n: int, trials: int = 20) -> bool: """Miller-Rabin素性测试(快速判断是否为质数)""" if n < 2: return False if n in (2, 3): return True if n % 2 == 0: return False # 将 n-1 写成 d * 2^s 的形式 d = n - 1 s = 0 while d % 2 == 0: d //= 2 s += 1 # 测试 for _ in range(trials): a = random.randrange(2, n - 1) x = pow(a, d, n) if x == 1 or x == n - 1: continue for _ in range(s - 1): x = pow(x, 2, n) if x == n - 1: break else: return False return True @timer def main_by_prime(n: int) -> None: for d in range(n, 0, -1): max_cycle = d - 1 max_d = d cycle = repeating_cycle_fermat(d) if max_cycle == cycle: print(f"{max_d} have {max_cycle} digits in its decimal fraction part.") return None if __name__ == "__main__": n = 10000 main_searchall(n) main_by_prime(n)