质数3, 7, 109, 和 673是值得注意的。将其中任意两个质数以任何顺序相连接产生的结果都是质数。
例如,取7和109,连接而成的7109和1097都是质数。这四个质数的和是792,这也是满足这个性质的四个质数集合的最小总和。
找出满足这个性质的五个质数的集合中,集合数之和最小的。算出这个最小的和。
import time
def get_primes(n):
""" n以下质数 """
n_set = set(range(3, n, 2))
for i in range(3, n, 2):
if i in n_set:
i_set = set(range(i * 2, n, i))
n_set -= i_set
return n_set
def is_prime(x):
""" x是否质数 """
if x < n_max:
if x in primes_set:
return True
else:
return False
x_sqrt = int(pow(x, 0.5))
l = [2]
l.extend(range(3, x_sqrt + 1, 2))
for i in l:
if x % i == 0:
return False
return True
def check_prime_pair(p1, p2):
""" 将其中任意两个质数以任何顺序相连接产生的结果都是质数 """
p1_p2 = int('%d%d' % (p1, p2))
if p1_p2 not in primes_set:
if not is_prime(p1_p2):
return False
p2_p1 = int('%d%d' % (p2, p1))
if p2_p1 not in primes_set:
if not is_prime(p2_p1):
return False
return True
def prime_pair(p):
""" 能与p组合以任何顺序相连接产生的结果都是质数的质数集 """
if p in primes_dict:
return primes_dict[p]
primes = set()
for j in range(primes_list.index(p) + 1, len(primes_list)):
p_ = primes_list[j]
if check_prime_pair(p, p_):
primes.add(p_)
primes_dict[p] = primes
return primes
def get_prime_set(p, pairs, sum_max):
""" 递归,五个质数的集合 """
if sum(p) + (5 - len(p)) * max(p) >= sum_max:
return sum_max
if len(p) == 4:
p.add(min(pairs))
print(p)
return sum(p)
for pp in pairs:
pairs_ = pairs & prime_pair(pp)
if len(pairs_) == 0:
continue
p_ = p.copy()
p_.add(pp)
sum_max_ = get_prime_set(p_, pairs_, sum_max)
if sum_max_ < sum_max:
sum_max = sum_max_
return sum_max
t1 = time.time()
n_max = 10000
primes_set = get_primes(n_max) - {5}
sum_max = float('inf')
primes_dict = {}
# 按与3的余数划分质数集
# 余数为1的数只能与余数为1的数和3组合
# 余数为2的数只能与余数为2的数和3组合
for mod_3 in [2, 1]:
primes_list = [p for p in primes_set if p % 3 != mod_3]
primes_list.sort()
for i1 in range(len(primes_list)):
v1 = primes_list[i1]
if v1 * 5 >= sum_max:
break
v1_prime_pair = prime_pair(v1)
for i2 in range(i1 + 1, len(primes_list)):
v2 = primes_list[i2]
if v1 + v2 * 4 >= sum_max:
break
if v2 not in v1_prime_pair:
continue
v2_prime_pair = prime_pair(v2)
for i3 in range(i2 + 1, len(primes_list)):
v3 = primes_list[i3]
if v1 + v2 + v3 * 3 >= sum_max:
break
if v3 not in v1_prime_pair or v3 not in v2_prime_pair:
continue
v3_prime_pair = prime_pair(v3)
for i4 in range(i3 + 1, len(primes_list)):
v4 = primes_list[i4]
if v1 + v2 + v3 + v4 * 2 >= sum_max:
break
if v4 not in v1_prime_pair or v4 not in v2_prime_pair or v4 not in v3_prime_pair:
continue
v4_prime_pair = prime_pair(v4)
for i5 in range(i4 + 1, len(primes_list)):
v5 = primes_list[i5]
if v1 + v2 + v3 + v4 + v5 >= sum_max:
break
if v5 not in v1_prime_pair or v5 not in v2_prime_pair or v5 not in v3_prime_pair or v5 not in v4_prime_pair:
continue
sum_max = v1 + v2 + v3 + v4 + v5
print(v1, v2, v3, v4, v5)
print(sum_max)
t2 = time.time()
print(t2 - t1)
t1 = time.time()
n_max = 10000
primes_set = get_primes(n_max) - {5}
primes_dict = {}
sum_max = float('inf')
# 按与3的余数划分质数集
# 余数为1的数只能与余数为1的数和3组合
# 余数为2的数只能与余数为2的数和3组合
for mod_3 in [2, 1]:
primes_list = [p for p in primes_set if p % 3 != mod_3]
primes_list.sort()
for i in primes_list:
sum_max = get_prime_set({i}, prime_pair(i), sum_max)
print(sum_max)
t2 = time.time()
print(t2 - t1)