50题暂算解决吧……但速度依然不是很满意。

This commit is contained in:
2026-03-17 17:18:41 +08:00
parent 4c59a84d47
commit 3358e97dd4

View File

@@ -14,12 +14,14 @@ from math import isqrt, log
from bitarray import bitarray
_prime_cache = set()
def timer(func):
def wrapper(*args, **kwargs):
start_time = time.time()
start_time = time.perf_counter()
result = func(*args, **kwargs)
end_time = time.time()
end_time = time.perf_counter()
elapsed_time = end_time - start_time
print(f"{func.__name__} time: {elapsed_time:.6f} seconds")
return result
@@ -27,9 +29,16 @@ def timer(func):
return wrapper
def primes_list(limit: int = 10**6) -> list[int]:
if limit < 2:
def n_primes(n: int = 4000) -> list[int]:
if n < 0:
raise ValueError("n must be a positive integer")
if n == 0:
return []
if n == 1:
return [2]
# 使用Dusart方法估计上限
limit = int(n * (log(n) + log(log(n)) - 0.5))
# 初始化全1假设都是素数0和1置为0
is_prime = bitarray(limit + 1)
@@ -45,7 +54,38 @@ def primes_list(limit: int = 10**6) -> list[int]:
is_prime[i * i : limit + 1 : i] = False
# 提取结果
return [i for i, val in enumerate(is_prime) if val]
result = []
for i, val in enumerate(is_prime):
if val:
result.append(i)
if len(result) >= n:
break
return result
def is_prime(num: int) -> bool:
if num in _prime_cache:
return True
if num < 2:
return False
if num in (2, 3):
_prime_cache.add(num)
return True
if num % 2 == 0 or num % 3 == 0:
return False
# 检查6k±1形式的因子
i = 5
w = 2
while i * i <= num:
if num % i == 0:
return False
i += w
w = 6 - w # 在2和4之间切换实现6k±1的检查
_prime_cache.add(num)
return True
def get_bound(limit: int = 10**6) -> int:
@@ -54,7 +94,7 @@ def get_bound(limit: int = 10**6) -> int:
"""
def f(t: float) -> float:
return t**2 * (2 * log(t) - 1) - 4 * limit
return t**2 * (2 * log(t) - 1) - 2 * limit
def fp(t: float) -> float:
return 4 * t * log(t)
@@ -66,9 +106,9 @@ def get_bound(limit: int = 10**6) -> int:
def max_primes_sum_best(limit: int = 10**6) -> tuple[int, int] | None:
# === 1. 确定搜索范围 ===
bound = get_bound(limit)
primes = primes_list(bound)
prime_set = set(primes)
primes = n_primes(bound)
# === 2. 构建前缀和数组 ===
# prefix[i] 表示前 i 个素数的和primes[0] 到 primes[i-1]
@@ -104,22 +144,15 @@ def max_primes_sum_best(limit: int = 10**6) -> tuple[int, int] | None:
# 计算连续素数之和primes[left] 到 primes[right-1]
consecutive_sum = prefix[right] - prefix[left]
# 修正:如果 sum 已经超过 limitleft 继续增大 sum 会减小,所以不应 break
# 但我们可以加一个判断:如果 prefix[right] - prefix[left] > limit且 left 还在增大...
# 实际上 left 增大sum 减小,所以一旦 sum < limit后续都 < limit
# 简单处理:直接检查,不 break或者可以预先判断但为清晰起见省略
if consecutive_sum >= limit:
continue # 跳过,但继续尝试更大的 leftsum 会变小)
if consecutive_sum in prime_set:
if is_prime(consecutive_sum):
length = right - left
if length > best_length:
best_length = length
best_prime = consecutive_sum
# 更新剪枝边界:后续需要找比当前更长的,所以 max_left 可以缩小
# 但 Python 的 range 已经确定,我们只需依赖外层的 right <= best_length 判断
return best_prime, best_length