✨ 新增欧拉第34、35题解法及说明
This commit is contained in:
80
solutions/0035.CircularPrimes/euler_35_better.py
Normal file
80
solutions/0035.CircularPrimes/euler_35_better.py
Normal file
@@ -0,0 +1,80 @@
|
||||
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
|
||||
|
||||
|
||||
# ---------- 1. PRIMES ----------
|
||||
MAX = 1_000_000
|
||||
is_p = bytearray(b"\1") * MAX # 1 表示素数,0 表示合数(与原来相反,方便理解)
|
||||
is_p[0] = is_p[1] = 0 # 0和1不是素数
|
||||
|
||||
# 优化:使用标准埃拉托斯特尼筛法
|
||||
for p in range(2, int(MAX**0.5) + 1):
|
||||
if is_p[p]:
|
||||
is_p[p * p : MAX : p] = b"\0" * ((MAX - p * p - 1) // p + 1)
|
||||
|
||||
|
||||
# ---------- 2. SCROLLING ----------
|
||||
def rotations(n: int) -> list[int]:
|
||||
"""返回 n 的所有旋转(数学移位版,无字符串开销)"""
|
||||
if n < 10:
|
||||
return [n]
|
||||
s = str(n)
|
||||
k = len(s)
|
||||
res = []
|
||||
for i in range(k):
|
||||
# 使用切片旋转,避免重复计算
|
||||
rotated = int(s[i:] + s[:i])
|
||||
res.append(rotated)
|
||||
return res
|
||||
|
||||
|
||||
# ---------- 3. MAIN ----------
|
||||
@timer
|
||||
def main(limit: int = MAX) -> int:
|
||||
# 预过滤:只要含 0,2,4,5,6,8 就可以跳过(除了2和5本身)
|
||||
bad_digits = set("024568")
|
||||
total = 0
|
||||
counted = set() # 用于去重,避免重复计数
|
||||
|
||||
for p in range(2, limit):
|
||||
if is_p[p]: # p是素数
|
||||
# 快速数字过滤(2和5是特例)
|
||||
if p != 2 and p != 5:
|
||||
s = str(p)
|
||||
if not bad_digits.isdisjoint(s):
|
||||
continue
|
||||
|
||||
# 如果已经统计过,跳过
|
||||
if p in counted:
|
||||
continue
|
||||
|
||||
# 检查所有旋转
|
||||
rs = rotations(p)
|
||||
|
||||
# 检查所有旋转数是否都是素数
|
||||
valid = True
|
||||
for r in rs:
|
||||
if r >= limit or not is_p[r]:
|
||||
valid = False
|
||||
break
|
||||
|
||||
if valid:
|
||||
# 如果是循环素数,统计并标记已计数
|
||||
total += len(set(rs)) # 使用set避免重复旋转
|
||||
counted.update(rs)
|
||||
|
||||
return total
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(f"循环素数数量: {main()}")
|
||||
Reference in New Issue
Block a user