我正在研究Project Euler Problem 50,它指出:
The prime 41,can be written as the sum of six consecutive primes:
41 = 2 + 3 + 5 + 7 + 11 + 13
This is the longest sum of consecutive primes that adds to a prime below one-hundred.The longest sum of consecutive primes below one-thousand that adds to a prime,contains 21 terms,and is equal to 953.
Which prime,below one-million,can be written as the sum of the most consecutive primes?
为了确定素数P中的项(如果它可以写成素数的总和),我使用所有素数的滑动窗口(按递增顺序)直到(但不包括)P,并计算所有的总和这些窗口,如果总和等于考虑的素数,我算一下窗口的长度……
这适用于1000以下的所有素数,但是对于高达10 ** 6的素数来说它非常慢,所以我希望备忘录会有所帮助;在计算滑动窗口的总和时,做了很多双重工作……(对吧?)
所以我在网上找到了标准的memoizaton实现,并将其粘贴在我的代码中,这是正确的吗? (我不知道应该怎么在这里工作……)
primes = tuple(n for n in range(1,10**6) if is_prime(n)==True)
count_best = 0
##http://docs.python.org/release/2.3.5/lib/itertools-example.html:
## Slightly modified (first for loop)
from itertools import islice
def window(seq):
for n in range(2,len(seq) + 1):
it = iter(seq)
result = tuple(islice(it,n))
if len(result) == n:
yield result
for elem in it:
result = result[1:] + (elem,)
yield result
def memoize(function):
cache = {}
def decorated_function(*args):
if args in cache:
return cache[args]
else:
val = function(*args)
cache[args] = val
return val
return decorated_function
@memoize
def find_lin_comb(prime):
global count_best
for windows in window(primes[0 : primes.index(prime)]):
if sum(windows) == prime and len(windows) > count_best:
count_best = len(windows)
print('Prime: ',prime,'Terms: ',count_best)
##Find them:
for x in primes[::-1]: find_lin_comb(x)
所有的输入都很受欢迎,我只是一个业余爱好程序员,所以请不要对我有所了解.
谢谢!
编辑:这是一个没有破坏缩进的工作代码粘贴:
http://pastebin.com/R1NpMqgb
This works fine for all primes up to 1000,but for primes up to 10**6 it is very slow,so I was hoping memozation would help; when calculating the sum of sliding windows,a lot of double work is done…(right?)
是的,对.当然,对于高达106的素数而言,它的速度很慢.
假设您有n个素数到N,按递增顺序编号,p_1 = 2,p_2 = 3,….当考虑是否素数没有. k是连续素数的总和,你考虑所有窗口[p_i,…,p_j],对于对(i,j),其中i <1. j< ķ.它们有(k-1)*(k-2)/ 2.通过所有k到n,你总共检查了n³/ 6个窗口(计算多重性,你在总共n-j次检查w(i.j)).即使忽略创建窗口并对其进行求和的成本,您也可以看到它如何严重缩放:
>对于N = 1000,要检查n = 168个素数和约790000个窗口(计算多重性).
>对于N = 10 ** 6,有n = 78498个素数和大约8.3 * 10 ** 13个窗口需要检查.
现在考虑创建和求和窗口的工作,估计它在ji 1低,用于求和w(i,j)中的ji 1素数,p_k的工作约为k³/ 6,总工作量大约为k * * 4/24中. N = 1000,花生等3300万步,但N = 1000000,接近1.6 * 10 ** 18.
一年包含大约3.1 * 10 ** 7秒,具有~3GHz的cpu,大约1017个时钟周期.所以我们谈论的是需要100个cpu年的操作(可能是10个左右的因素).
你想,你不愿意等那么久;)
现在,通过记忆,你仍然可以多次查看每个窗口,但是你只对每个窗口进行一次计算.这意味着您需要大约n³/ 6的工作来计算窗口,并在任何窗口看一下n³/ 6次.
>问题1:您仍需要查看大约8.3 * 10 ** 13次的窗口,即使只花费一个周期,也需要几个小时.
>问题2:有大约8.3 * 10 ** 13个窗口要记忆.你没有那么多的记忆,除非你可以使用一个非常大的高清.
您可以通过丢弃不再需要的数据来规避内存问题,并且只在需要时计算窗口的数据,但是一旦您知道可能会丢弃哪些数据,您应该能够看到更好的方法.
The longest sum of consecutive primes below one-thousand that adds to a prime,and is equal to 953.
这告诉你关于产生这笔金额的窗口是什么?哪里可以开始,哪里可以停止?如何使用该信息创建一个有效的算法来解决问题?