在python中执行素数值对
我目前被困在欧拉计划问题60上。问题是这样的: 素数3、7、109和673是非常显著的。通过取任意两个素数并以任意顺序连接它们,结果将始终是素数。例如,取7和109,7109和1097都是素数。这四个素数之和792表示具有此属性的四个素数集合的最小和 求一组五个素数的最小和,其中任意两个素数连接起来生成另一个素数 在Python中,我使用并创建了以下函数在python中执行素数值对,python,primes,Python,Primes,我目前被困在欧拉计划问题60上。问题是这样的: 素数3、7、109和673是非常显著的。通过取任意两个素数并以任意顺序连接它们,结果将始终是素数。例如,取7和109,7109和1097都是素数。这四个素数之和792表示具有此属性的四个素数集合的最小和 求一组五个素数的最小和,其中任意两个素数连接起来生成另一个素数 在Python中,我使用并创建了以下函数 def isprime(n): """Primality test using 6k+-1 optimi
def isprime(n):
"""Primality test using 6k+-1 optimization."""
if n <= 3:
return n > 1
elif n % 2 == 0 or n % 3 == 0:
return False
i = 5
while i * i <= n:
if n % i == 0 or n % (i + 2) == 0:
return False
i += 6
return True
def prime_pair_sets(n):
heap = [[3,7]]
x = 11
#Phase 1: Create a list of length n.
while getMaxLength(heap)<n:
if isprime(x):
m = [x]
for lst in heap:
tmplst = [x]
for p in lst:
if primePair(x,p):
tmplst.append(p)
if len(tmplst)>len(m):
m=tmplst
heap.append(m)
x+=2
s = sum(maxList(heap))
#Phase 2: Find the lowest sum.
for li in heap:
y=x
while s>(sum(li)+y) and len(li)<n:
b = True
for k in li:
if not primePair(k,y):
b = False
if b == True:
li.append(y)
y+=2
if len(li)>=n:
s = sum(li)
return s
def getMaxLength(h):
m = 0
for s in h:
if len(s) > m:
m = len(s)
return m
def primePair(x, y):
return isprime(int(str(x)+str(y))) and isprime(int(str(y)+str(x)))
def maxList(h):
result = []
for s in h:
if len(s)> len(result):
result = s
return result
我仅使用第一阶段执行primePairSets函数。经过大约一个小时的等待,我得到了7461733647+23003+16451+1493+23的总数。事实证明,这不是我们想要的金额。我用两个阶段再次尝试了这个问题。大约两个小时后,我得到了同样的错误结果。显然,答案不到74617。有人能帮我找到一个更有效的方法来解决这个问题吗。请告诉我如何解决它。找到解决方案
素数:135197570167338389
总数:26033
运行时间减少到约10秒,而OP solution报告的运行时间为1-2小时。
接近
基于扩展包含素数列表路径的回溯算法
如果一个素数与路径中已有的所有素数成对,则可以将其添加到路径中
使用Eratosthenes筛预先计算素数,直到达到我们预期需要的最大值
对于每个素数,预先计算它与哪个素数成对
代码
运行时间
n max_prime Primes Found Run Time (secs)
2 1000 (3, 7) 0.1280
3 1000 (3, 37, 67) 0.1240
4 1000 (3, 7, 109, 673) 0.1233
5 40,000 (13, 5197, 5701, 6733, 8389) 7.1142
注意:上面的计时在较旧的Windows桌面计算机上执行,
即:
约7岁的HP Pavilion台式机i7 CPU 920@2.67 GHz
解决方案
素数:135197570167338389
总数:26033
运行时间减少到约10秒,而OP solution报告的运行时间为1-2小时。
接近
基于扩展包含素数列表路径的回溯算法
如果一个素数与路径中已有的所有素数成对,则可以将其添加到路径中
使用Eratosthenes筛预先计算素数,直到达到我们预期需要的最大值
对于每个素数,预先计算它与哪个素数成对
代码
运行时间
n max_prime Primes Found Run Time (secs)
2 1000 (3, 7) 0.1280
3 1000 (3, 37, 67) 0.1240
4 1000 (3, 7, 109, 673) 0.1233
5 40,000 (13, 5197, 5701, 6733, 8389) 7.1142
注意:上面的计时在较旧的Windows桌面计算机上执行,
即:
约7岁的HP Pavilion台式机i7 CPU 920@2.67 GHz
我写这段代码是基于一个Eratosthenes筛,它只存储数字1 mod 6和-1 mod 6。它非常快
def find_lowest_sum (pmax,num):
n=int(str(pmax)+str(pmax))
sieve5m6 = [True] * (n//6+1)
sieve1m6 = [True] * (n//6+1)
for i in range(1,int((n**0.5+1)/6)+1):
if sieve5m6[i]:
sieve5m6[6*i*i::6*i-1]=[False]*(((n//6+1)-6*i*i-1)//(6*i-1)+1)
sieve1m6[6*i*i-2*i::6*i-1]=[False]*(((n//6+1)-6*i*i+2*i-1)//(6*i-1)+1)
if sieve1m6[i]:
sieve5m6[6*i*i::6*i+1]=[False]*(((n//6+1)-6*i*i-1)//(6*i+1)+1)
sieve1m6[6*i*i+2*i::6*i+1]=[False]*(((n//6+1)-6*i*i-2*i-1)//(6*i+1)+1)
def test_concatenate (p1,p2):
ck=0
p3=int(str(p1)+str(p2))
if sieve1m6[(p3-1)//6] and p3%6==1:
ck=1
elif sieve5m6[(p3+1)//6]and p3%6==5:
ck=1
if ck==1:
p3=int(str(p2)+str(p1))
if sieve1m6[(p3-1)//6] and p3%6==1:
ck=2
elif sieve5m6[(p3+1)//6]and p3%6==5:
ck=2
if ck==2:
return True
else:
return False
kmax=(pmax+1)//6
s1=5*pmax
P1=[]
P2=[]
p=3
kmin=0
while p<s1//5:
if p==3 or(p%6==1 and sieve1m6[(p-1)//6])or(p%6==5 and sieve5m6[(p+1)//6]):
P=[]
if p%6==1:
kmin=p//6
elif p%6==5:
kmin=(p+1)//6
if sieve1m6[kmin]:
if test_concatenate(p,6*kmin+1):
P.append(6*kmin+1)
for k in range(kmin+1,kmax):
if sieve5m6[k]:
if test_concatenate(p,6*k-1):
P.append(6*k-1)
if sieve1m6[k]:
if test_concatenate(p,6*k+1):
P.append(6*k+1)
i1=0
while i1<len(P) and P[i1]<s1:
P1=[p]
s=p
P1.append(P[i1])
s+=P[i1]
for i2 in range(i1+1,len(P)):
for i3 in range(1,len(P1)):
ck=test_concatenate(P[i2],P1[i3])
if ck==False:
break
if len(P1)-1==i3 and ck==True:
P1.append(P[i2])
s+=P[i2]
if len(P1)==num:
if s<s1:
P2=P1
s1=s
break
i1+=1
p+=2
return P2
P=find_lowest_sum(9001,5)
print(P)
s=0
for i in range(0,len(P)):
s+=P[i]
print(s)
我写这段代码是基于一个Eratosthenes筛,它只存储数字1 mod 6和-1 mod 6。它非常快
def find_lowest_sum (pmax,num):
n=int(str(pmax)+str(pmax))
sieve5m6 = [True] * (n//6+1)
sieve1m6 = [True] * (n//6+1)
for i in range(1,int((n**0.5+1)/6)+1):
if sieve5m6[i]:
sieve5m6[6*i*i::6*i-1]=[False]*(((n//6+1)-6*i*i-1)//(6*i-1)+1)
sieve1m6[6*i*i-2*i::6*i-1]=[False]*(((n//6+1)-6*i*i+2*i-1)//(6*i-1)+1)
if sieve1m6[i]:
sieve5m6[6*i*i::6*i+1]=[False]*(((n//6+1)-6*i*i-1)//(6*i+1)+1)
sieve1m6[6*i*i+2*i::6*i+1]=[False]*(((n//6+1)-6*i*i-2*i-1)//(6*i+1)+1)
def test_concatenate (p1,p2):
ck=0
p3=int(str(p1)+str(p2))
if sieve1m6[(p3-1)//6] and p3%6==1:
ck=1
elif sieve5m6[(p3+1)//6]and p3%6==5:
ck=1
if ck==1:
p3=int(str(p2)+str(p1))
if sieve1m6[(p3-1)//6] and p3%6==1:
ck=2
elif sieve5m6[(p3+1)//6]and p3%6==5:
ck=2
if ck==2:
return True
else:
return False
kmax=(pmax+1)//6
s1=5*pmax
P1=[]
P2=[]
p=3
kmin=0
while p<s1//5:
if p==3 or(p%6==1 and sieve1m6[(p-1)//6])or(p%6==5 and sieve5m6[(p+1)//6]):
P=[]
if p%6==1:
kmin=p//6
elif p%6==5:
kmin=(p+1)//6
if sieve1m6[kmin]:
if test_concatenate(p,6*kmin+1):
P.append(6*kmin+1)
for k in range(kmin+1,kmax):
if sieve5m6[k]:
if test_concatenate(p,6*k-1):
P.append(6*k-1)
if sieve1m6[k]:
if test_concatenate(p,6*k+1):
P.append(6*k+1)
i1=0
while i1<len(P) and P[i1]<s1:
P1=[p]
s=p
P1.append(P[i1])
s+=P[i1]
for i2 in range(i1+1,len(P)):
for i3 in range(1,len(P1)):
ck=test_concatenate(P[i2],P1[i3])
if ck==False:
break
if len(P1)-1==i3 and ck==True:
P1.append(P[i2])
s+=P[i2]
if len(P1)==num:
if s<s1:
P2=P1
s1=s
break
i1+=1
p+=2
return P2
P=find_lowest_sum(9001,5)
print(P)
s=0
for i in range(0,len(P)):
s+=P[i]
print(s)
使用埃拉托斯烯筛进行初步检查,这将节省大量时间。如果部分列表中有3个元素,则需要将任何新候选元素与所有3个现有元素(前缀和后缀)进行对比检查。使用Eratosthenes筛选进行基本检查,这将节省大量时间。如果部分列表中有3个元素,则需要将任何新候选元素与所有3个现有元素(前缀和后缀)进行对比。