这个问题的题目是:
Find the smallest number that can be expressed as
the sum of 7 consecutive prime numbers,
the sum of 21 consecutive prime numbers,
the sum of 481 consecutive prime numbers,
the sum of 851 consecutive prime numbers,
and is itself a prime number.
For example, 41 is the smallest prime number that can be expressed as
the sum of 3 consecutive primes (11 + 13 + 17 = 41) and
the sum of 6 consecutive primes (2 + 3 + 5 + 7 + 11 + 13 = 41).
我解决这个问题的思路是先生成一个一定数量的质数的集合,我从网上这个地址下载了些质数。然后分别计算出7个,21个,481个,851个连续质数的和的集合,然后它们五个集合的交集中的最小的数就是答案了。我用c来做的。尽管做出了答案5614957,但我发现了许多问题。我到底需要多少个质数,如果数的大小超出整型的表示范围,内存的使用量太大。
网上有许多充满了创意的方法。一个朋友只用一些unix工具就解决了问题。它是这样做的:
第一步:从网上下载质数
$ for i in $(seq 50); do wget "http://primes.utm.edu/lists/small/millions/primes$i.zip"; done
第二步:解压文件
$ for i in $(seq 50); do unzip "primes$i.zip" && rm -f "primes$i.zip"; done
第三步:把质数按一行一个存储到一个文件中
for i in $(seq 50); do (awk 'BEGIN { OFS="/n" } NR > 2 {print $1,$2,$3,$4,$5,$6,$7,$8}' primes$i.txt >> primes.txt) && rm -f primes$i.txt; done
第四步:确定处理过程中没有遗漏
$ wc -l primes.txt
输出:50000000 primes.txt
第五步:创建四个文件,分别存储7,17,41,541个连续质数的和
$ last=$(tail -1 primes.txt)
$ for N in 7 17 41 541
do
awk 'BEGIN { prev[0] = 0 } NR < '$N' {prev[NR] = $1; sum += $1 } NR >= '$N' { psum += prev[NR-'$N']; delete prev[NR-'$N']; prev[NR] = $1; sum += $1; if (sum - psum > '$last') { exit } printf "%d/n", sum - psum }' primes.txt > primes$N.txt
done
第六步:求交集
$ sort -nm primes541.txt primes41.txt | uniq -d | sort -nm primes17.txt - | uniq -d | sort -nm primes7.txt - | uniq -d
第七步:确定结果是质数
$ grep -m1 7830239 primes.txt
我知道这样做要很长时间,但至少应该比我的短。虽然我的程序只用了不到一秒,但编写代码花了很多时间。所以这是个充满创意,还不错的方法。我还发现了一个更好的方法。用python编写,使用了python里面的迭代器。这个问题可以当做使用python迭代器的经典范例。我在这篇文章中来说明这个方法。