From 9762ba3f0cd1bdf699054bd2788579c9f3807833 Mon Sep 17 00:00:00 2001 From: Sidney Zhang Date: Tue, 16 Dec 2025 18:37:17 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat(eular=5F12.py)=EF=BC=9A?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0Miller-Rabin=E7=B4=A0=E6=80=A7=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E5=92=8CPollard's=20Rho=E7=AE=97=E6=B3=95=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0=E8=B4=A8=E5=9B=A0=E6=95=B0=E5=88=86=E8=A7=A3=20?= =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactor(eular=5F12.py)=EF=BC=9A=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E4=BB=A3=E7=A0=81=E7=BB=93=E6=9E=84=EF=BC=8C=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E6=95=B0=E5=AD=A6=E6=96=B9=E6=B3=95main=5Fmath()?= =?UTF-8?q?=E7=94=A8=E4=BA=8E=E9=AB=98=E6=95=88=E8=AE=A1=E7=AE=97=E4=B8=89?= =?UTF-8?q?=E8=A7=92=E5=BD=A2=E6=95=B0=E7=9A=84=E7=BA=A6=E6=95=B0=E4=B8=AA?= =?UTF-8?q?=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- solutions/0012.TriangularNumber/eular_12.py | 132 ++++++++++++++++++++ 1 file changed, 132 insertions(+) diff --git a/solutions/0012.TriangularNumber/eular_12.py b/solutions/0012.TriangularNumber/eular_12.py index 69c1d27..458ed49 100644 --- a/solutions/0012.TriangularNumber/eular_12.py +++ b/solutions/0012.TriangularNumber/eular_12.py @@ -26,7 +26,13 @@ NOTE: """ import math +import random +import re import time +from collections import Counter +from functools import reduce +from math import gcd +from typing import List def timer(func): @@ -68,5 +74,131 @@ def main_coding() -> None: n += 1 +def is_probable_prime(n: int, trials: int = 10) -> 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 + + +def pollards_rho(n: int, max_iter: int = 100000) -> int | None: + """ + Pollard's Rho 算法:返回n的一个非平凡因子 + + Args: + n: 待分解的合数 + max_iter: 最大迭代次数防止无限循环 + + Returns: + n的一个因子(可能是质数也可能是合数) + 若失败返回None + """ + + if n % 2 == 0: + return 2 + + # 随机生成多项式 f(x) = x^2 + c (mod n) + c = random.randrange(1, n - 1) + + def f(x): + return (pow(x, 2, n) + c) % n + + # Floyd 判圈算法 + x = random.randrange(2, n - 1) + y = x + d = 1 + + iter_count = 0 + while d == 1 and iter_count < max_iter: + x = f(x) # 乌龟:走一步 + y = f(f(y)) # 兔子:走两步 + d = gcd(abs(x - y), n) + iter_count += 1 + + if d == n: + # 失败,尝试其他参数(递归或返回None) + return pollards_rho(n, max_iter) if max_iter > 1000 else None + + return d + + +def factorize(n: int | None) -> List[int | None]: + """ + 完整因数分解:递归分解所有质因数 + + Args: + n: 待分解的正整数 + + Returns: + 质因数列表(可能含重复) + """ + if n == 1: + return [] + if n is None: + return [None] + + # 如果是质数,直接返回 + if is_probable_prime(n): + return [n] + + # 获取一个因子 + factor = pollards_rho(n) + + if factor is None: + return [None] + + # 递归分解 + return factorize(factor) + factorize(n // factor) + + +def get_prime_factors(n: int) -> dict[int | None, int]: + """获取所有不重复的质因数""" + return dict(Counter(factorize(n))) + + +def zuheshu(tl: list[int]) -> int: + return reduce(lambda x, y: x * y, tl) + + +@timer +def main_math() -> None: + n = 1 + while True: + tn = get_triangle_number(n) + factors = get_prime_factors(tn) + if factors == {}: + n += 1 + continue + if zuheshu(list(factors.values())) > 500: + print(tn) + break + n += 1 + + if __name__ == "__main__": main_coding() + # main_math()