我想知道给定正数偶数的方式可以写成两个素数的总和。
目前,我有这段代码:
n = int(input(">"))
def genprimes(n):#generate primes from 2 to n
primes = []
for i in range(2,n):
prime = True
for a in range(2,i):
if i % a == 0:
prime = False
if prime == True:
primes.append(i)
return primes
pairs = []
primes = genprimes(n)
for prime1 in primes:
for prime2 in primes:
if prime1 + prime2 == n and [prime1,prime2] not in pairs and [prime2,prime1] not in pairs:
pairs.append([prime1,prime2])
print(len(pairs))
它有效,但当n
超过10,000
时,它会变得有点慢。任何人都可以想到一种更有效的方法来找到这个值,这样它可以为高值产生快速结果吗?
答案 0 :(得分:4)
你有两种慢速算法。
要获取素数列表,请分别检查每个号码是否为素数据。获得素数列表的最快方法是使用预先建立的素数列表 - 这就是我为这些问题所做的。最多2 ** 16(65,536)的素数列表只需要6542个整数,我将该列表存储在一个模块中。您可能更喜欢使用Sieve of Eratosthenes,这通常被认为是从头开始获取此类列表的最快方式。
然后尝试每对素数以查看它们是否添加到目标数字。对于每个素数p
,查看n-p
是否也是素数会快得多。您可以使用二进制搜索来检查n-p
,正如@Shubham建议的那样,但是有两个索引可能会更快,一个经常上升并产生p
而另一个下降需要检查{ {1}}。将您的主要列表复制到集合可能是最快的,并使用它来检查列表中是否n-p
。最后两种技术的顺序为n-p
,但对于仅高达10,000的数字,开销可能会影响哪种技术最佳。是的,对于这些问题,10,000不是很大。最后,如果内存不是问题,@ BondKeith指出你可以将主要列表作为布尔值列表(真/假)并且非常快速地检查n
是否为素数 - 这是最快的,如果最耗费内存的技术。
答案 1 :(得分:2)
这可以通过优化程序的两个部分来有效地完成。
首先,我们可以通过使用Sieve of Eratosthenes生成素数来优化genprimes()
,这可以在n
中生成素数O(nlog(log(n))
。
之后,一旦我们有了素数列表,我们就可以做到以下几点:
p1
。n-p1
。 如果p = number of primes till n
然后这部分的复杂性将是O(plog(p))
。
正如@PaulHankin建议的那样,根据@SrujanKumarGulla的回答,我们可以在获得主要列表后构建O(p)
解决方案。
第二部分的实施(第一部分是标准Sieve of Eratosthenes):
# prime list is assumed to be sorted. It will be if it's generated
# using Sieve of Eratosthenes
def solutions(n, prime_list):
low = 0, high = len(prime_list)-1
sol = []
while low < high:
temp = prime_list[low] + prime_list[high]
if temp == n:
sol.append((prime_list[low], prime_list[high], ))
elif temp < n:
low += 1
else:
high -= 1
return len(sol)
答案 2 :(得分:1)
如果内存不是问题,您可以通过以下方式进一步优化速度:
1)如果i是素数,则从2..n构建数组,其中array [i] = true。 (可以使用Eratosthenes的Sieve或者更高级的东西。)
2)对于所有2&lt; = i&lt; n / 2看看array [i]和array [n-i]是否都为真。如果是这样,那么我和n-i是一对。 (将i的上限设置为n / 2意味着您不必删除重复项。)
整个算法是O(n log n)。 (O(n log n)构建素数; O(n)求构。)
我是用C#而不是Python做的,但能够在10秒内找到n = 100,000,000的所有对。
答案 3 :(得分:1)
def prim(n):
primes = []
for num in range(1, n + 1): # current number check
limit = int(num ** 0.5) + 1 # search limit
for div in range(2, limit): # searching for divider
if (num % div) == 0: # divider found
break # exit the inner loop
else: # out of the inner loop
primes.append(num) # no divider found hence prime
return(primes)
num = int(input('Input an even number: '))
primes = prim(num) # create list of primes
for i in range(num//2 + 1):
if num % 2 != 0:
print(num, 'not even'); break
if i in primes and (num - i) in primes:
print(i, '+', num - i)
"""
Examples:
=========
Input an even number: 18
1 + 17
5 + 13
7 + 11
Input an even number: 88
5 + 83
17 + 71
29 + 59
41 + 47
Input an even number: 17
17 not even
"""
答案 4 :(得分:0)
这是来自Rory建议的实际解决方案,它使用Eratosthenes的Sieve来有效地生成素数,然后看n-prime
是否也是素数。
然后需要将解决方案的计数减半并四舍五入以防止重复。
n = int(input(">"))
def genprimes(n):
limitn = n+1
not_prime = set()
primes = []
for i in range(2, limitn):
if i in not_prime:
continue
for f in range(i*2, limitn, i):
not_prime.add(f)
primes.append(i)
return primes
nos=0
primes = genprimes(n)
for prime in primes:
if n-prime in primes:
nos += 1
print(str(int((nos/2)+0.5)))