106 lines
3.3 KiB
Python
106 lines
3.3 KiB
Python
"""
|
||
By replacing the 1st digit of the 2-digit number *3,
|
||
it turns out that six of the nine possible values: 13, 23, 43, 53, 73, and 83, are all prime.
|
||
|
||
By replacing the 3rd and 4th digits of 56**3 with the same digit,
|
||
this 5-digit number is the first example having seven primes among the ten generated numbers,
|
||
yielding the family: 56003, 56113, 56333, 56443, 56663, 56773, and 56993.
|
||
Consequently 56003, being the first member of this family, is the smallest prime with this property.
|
||
|
||
Find the smallest prime which,
|
||
by replacing part of the number (not necessarily adjacent digits) with the same digit,
|
||
is part of an eight prime value family.
|
||
|
||
-----
|
||
|
||
*.000*.、*.111*.、*.222*.、*.333*.、*.444*.、*.555*.、*.666*.、*.777*.、*.888*.、*.999*.
|
||
|
||
数字的形式就是这样,最多十个数,那么,就是要在质数序列上搜索这样的数列:
|
||
|
||
1. 用欧拉筛生成质数表(上限约100万足够)
|
||
2. 对每个质数p:
|
||
a. 检查是否有≥3个相同数字,且该数字∈{0,1,2}
|
||
b. 生成所有C(n,3)种3位替换组合
|
||
c. 对每种组合,用0-9替换,统计质数个数
|
||
d. 若得到8个质数,返回p(首个即为答案)
|
||
|
||
"""
|
||
|
||
import time
|
||
from itertools import combinations
|
||
from math import isqrt
|
||
|
||
from bitarray import bitarray
|
||
|
||
|
||
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**8) -> set[int]:
|
||
is_prime = bitarray(limit + 1)
|
||
is_prime.setall(True)
|
||
is_prime[:2] = False # 0和1不是素数
|
||
|
||
# 只需筛到 sqrt(n)
|
||
imax = isqrt(limit) + 1
|
||
|
||
for i in range(2, imax):
|
||
if is_prime[i]:
|
||
# 步长i,从i*i开始(小于i*i的已被更小的素数筛过)
|
||
is_prime[i * i : limit + 1 : i] = False
|
||
|
||
return {i for i, isp in enumerate(is_prime) if isp}
|
||
|
||
|
||
@timer
|
||
def solve() -> list[int]:
|
||
primes = primes_list(10**6)
|
||
|
||
# 遍历所有可能的模式
|
||
for prime in sorted(primes):
|
||
if prime < 1000: # 从4位数开始
|
||
continue
|
||
|
||
s = str(prime)
|
||
|
||
# 检查每个出现3次或以上的数字
|
||
for d in set(s):
|
||
positions = [i for i, c in enumerate(s) if c == d]
|
||
if len(positions) < 3:
|
||
continue
|
||
|
||
# 尝试替换3个位置
|
||
for combo in combinations(positions, 3):
|
||
if 0 in combo and d == "0":
|
||
continue
|
||
|
||
family = []
|
||
for new_d in "0123456789":
|
||
new_num_str = "".join(
|
||
new_d if i in combo else c for i, c in enumerate(s)
|
||
)
|
||
new_num = int(new_num_str)
|
||
|
||
# 确保长度相同且是素数
|
||
if len(str(new_num)) == len(s) and new_num in primes:
|
||
family.append(new_num)
|
||
|
||
if len(family) == 8:
|
||
return sorted(family)
|
||
|
||
return [-1]
|
||
|
||
|
||
if __name__ == "__main__":
|
||
result = solve()
|
||
print(result)
|