Problem 10 : Summation of primes
The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17.
Find the sum of all the primes below two million.
1. 第10个问题:质数的总和
小于10的质数的和是 2 + 3 + 5 + 7 = 17。
求小于200万的所有质数的总和。
2. 求解分析
第一句话描述了把小于10的四个质数的累加求和,结果是17。
第二句话提出了问题。第一种求解方法:我们可以从2开始到200万逐个数判断是否为质数,然后把所有质数累加求和,最后得到结果,但是这个效率比较低。这道题最好的方法是使用质数筛子,把200万以内的质数找出来,然后计算出所有的质数的总和。
3. C++ 代码实现
类PE0010包含两个成员变量 m_max 和 m_Sieve,m_max是定义最大的数,m_Sieve是质数筛子的指针。
函数createPrimeSieve()用来建质数筛子,结果保存在m_Sieve里。
构造函数PE0010()从堆上申请了内存空间,注意为了减少空间大小,数据类型是一个字节的bool,然后调用函数createPrimeSieve()。
函数getSumOfPrimes()则用来统计在质数筛子里满足条件的所有质数的总合。
C++代码实现还是很简洁高效的。
C++ 代码
#include <iostream>
#include <cstring> // memset()
#include <cmath> // sqrt()
#include <cassert> // assert()
using namespace std;
class PE0010
{
private:
static const int m_max = 2000000; // two million
bool *m_Sieve; // Prime Sieve
public:
PE0010() { m_Sieve = new bool [m_max+1]; createPrimeSieve(); }
~PE0010() { delete [] m_Sieve; }
void createPrimeSieve();
long long getSumOfPrimes(int number = m_max);
};
// create a prime Sieve of Eratosthenes below max value
void PE0010::createPrimeSieve()
{
memset(m_Sieve, true, (m_max+1)*sizeof(bool));
m_Sieve[0] = m_Sieve[1] = false;
for (int i=2; i<=(int)sqrt((double)m_max); i++)
{
if (true == m_Sieve[i])
{
for (int j=i*i; j<m_max; j+=i)
{
m_Sieve[j] = false;
}
}
}
}
// calculate sum of all primes below number
long long PE0010::getSumOfPrimes(int number)
{
long long sum = 2; // first prime prime is 2
for (int n=3; n<number; n+=2) // primes above 2 are odd
{
if (true == m_Sieve[n])
{
sum += n;
}
}
return sum;
}
int main()
{
PE0010 pe0010;
assert(17 == pe0010.getSumOfPrimes(10));
cout << "The sum of all the primes below two million is " ;
cout << pe0010.getSumOfPrimes() << "." << endl;
return 0;
}
4. Python 代码实现
Python实现跟C++思路差不多,但更简洁一些。函数createPrimeSieve()创建质数筛子,然后返回质数的列表。
函数getSumOfPrimes()直接调用函数sum()来对质数列表中的所有质数求和。
Python 代码
def createPrimeSieve(n):
""" create prime sieve """
sieve = [True] * n
sieve[0] = sieve[1] = False
for i in range(2, int(n**0.5)+1):
if True == sieve[i]:
for j in range(i*i, n, i):
sieve[j] = False
return [i for i in range(1, n) if sieve[i]]
def getSumOfPrimes(n):
""" compute sum of all primes in list """
return sum(createPrimeSieve(n))
def main():
assert 17 == getSumOfPrimes(10)
print("The sum of all the primes below two million is %d."\
% getSumOfPrimes(2*10**6))
if __name__ == '__main__':
main()