51题完成解决
This commit is contained in:
105
solutions/0051.PrimeDigitReplace/euler_51_better.py
Normal file
105
solutions/0051.PrimeDigitReplace/euler_51_better.py
Normal file
@@ -0,0 +1,105 @@
|
||||
"""
|
||||
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)
|
||||
Reference in New Issue
Block a user