""" The prime 41, can be written as the sum of six consecutive primes: 41 = 2 + 3 + 5 + 7 + 11 + 13 This is the longest sum of consecutive primes that adds to a prime below one-hundred. The longest sum of consecutive primes below one-thousand that adds to a prime, contains 21 terms, and is equal to 953. Which prime, below one-million, can be written as the sum of the most consecutive primes? """ import time def timer(func): def wrapper(*args, **kwargs): start_time = time.time() result = func(*args, **kwargs) end_time = time.time() elapsed_time = end_time - start_time print(f"{func.__name__} time: {elapsed_time:.6f} seconds") return result return wrapper def primes_list(limit: int = 10**6) -> list[int]: if limit < 2: return [] is_prime = bytearray(b"\x01") * limit is_prime[0:2] = b"\x00\x00" # 更简洁的写法,同时置0和1 # 埃氏筛,使用切片赋值加速 # int(limit**0.5) 等价于 isqrt(limit)(Python 3.8+ 可用 math.isqrt) for i in range(2, int(limit**0.5) + 1): if is_prime[i]: start = i * i # 计算切片长度:从 start 到 limit,步长 i 的元素个数 count = (limit - start + i - 1) // i # 等效于 ceil((limit-start)/i) if count > 0: is_prime[start:limit:i] = b"\x00" * count return [i for i in range(limit) if is_prime[i]] def max_primes_sum(limit: int = 10**6) -> tuple: primes = primes_list(limit) prime_set = set(primes) # 计算从2开始连续加素数,最多能加多少个不超过limit max_possible_len = 0 temp_sum = 0 for p in primes: temp_sum += p if temp_sum >= limit: break max_possible_len += 1 # 从最长可能长度往下枚举 for length in range(max_possible_len, 0, -1): # 滑动窗口:计算连续length个素数的和 window_sum = sum(primes[:length]) if window_sum >= limit: continue # 滑动窗口遍历所有起始位置 for start in range(len(primes) - length): if window_sum in prime_set: return window_sum, length # 滑动:减去头部,加上尾部 window_sum += primes[start + length] - primes[start] if window_sum >= limit: break return 0, 0 @timer def main(): limit = int(input("limit:")) max_sum, max_length = max_primes_sum(limit) print(f"max primt: {max_sum}, max_length: {max_length}") if __name__ == "__main__": main()