✨ feat(eular_12.py):添加Miller-Rabin素性测试和Pollard's Rho算法实现质因数分解
♻️ refactor(eular_12.py):优化代码结构,新增数学方法main_math()用于高效计算三角形数的约数个数
This commit is contained in:
@@ -26,7 +26,13 @@ NOTE:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import math
|
import math
|
||||||
|
import random
|
||||||
|
import re
|
||||||
import time
|
import time
|
||||||
|
from collections import Counter
|
||||||
|
from functools import reduce
|
||||||
|
from math import gcd
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
|
||||||
def timer(func):
|
def timer(func):
|
||||||
@@ -68,5 +74,131 @@ def main_coding() -> None:
|
|||||||
n += 1
|
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__":
|
if __name__ == "__main__":
|
||||||
main_coding()
|
main_coding()
|
||||||
|
# main_math()
|
||||||
|
|||||||
Reference in New Issue
Block a user