C ++:Eratosthenes的筛子并不总是有效

时间:2014-08-07 21:32:35

标签: c++ sieve-of-eratosthenes

我正在制作一个C ++程序,使用Sieve of Eratosthenes

查找素数

目前我有以下代码:

C ++

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

class is_multiple_of {
    int m_div;
public:
    is_multiple_of(int div) : m_div(div) {}
    bool operator()(int n) { return ((n > m_div) && (0 == n % m_div)); }
};

int main ()
{
    vector<int> v;
    for (int i=2; i<=100; i++) v.push_back(i);

    v.erase( remove_if(v.begin(), v.end(), is_multiple_of(2)), v.end() );
    v.erase( remove_if(v.begin(), v.end(), is_multiple_of(3)), v.end() ); 
    v.erase( remove_if(v.begin(), v.end(), is_multiple_of(5)), v.end() ); 
    v.erase( remove_if(v.begin(), v.end(), is_multiple_of(7)), v.end() ); 

    for (unsigned i=0; i<v.size(); ++i)
        cout << v[i] << " ";


    cout << endl << v.size();
    return 0;
}

工作正常,即它表示在1到100之间有25个素数(即correct)。但是,如果我想知道前500个素数,例如,它会说有118个实际上有95个。要纠正这个问题,我必须添加更多倍数来移除ie v.erase( remove_if(v.begin(), v.end(), is_multiple_of(11)), v.end() );然后添加更多is_multiple_of()的。

有没有办法让它更有效率,而不仅仅是让它删除更多的先前找到的素数?

1 个答案:

答案 0 :(得分:1)

由于您要实现查找素数的版本,因此以下内容应该有效(我们使用的是500)

 int stopInt = static_cast<int>(sqrt(500));
 int j = 0;
 for (int i = 0; i < stopInt; ++i, ++j)
     v.erase(remove_if(v.begin(), v.end(), is_multiple_of(v[j])), v.end());

以下是#34;标记&#34;只需将它们移动到向量的末尾即可:

     vector<int>::iterator sMarked = v.end();
     int stopInt = static_cast<int>(sqrt(500));
     int j = 0;
     for (int i = 0; i < stopInt; ++i, ++j)
         sMarked = remove_if(v.begin(), sMarked, is_multiple_of(v[j]));
     v.erase(sMarked, v.end());

因此,我们通过跟踪remove_if的返回值来不断标记元素。然后在最后,我们做一个单vector::erase来删除倍数。这应该比在循环中不断调用v_erase更有效。