埃氏筛法
算法:从小到大枚举素数,他们的倍数是合数,筛掉。下面是算法的实现程序:
#include <iostream>
#include <cmath>
#include <cstring>
using namespace std;
int main()
{
int n;
int a[10000] = {0};
cin >> n;
int m = sqrt(n) + 1;
for(int i = 2;i <= m;i++)
{
if(!a[i])
for(int j = i * i;j <= n;j += i)
a[j] = 1;
}
int c = 0;
for(int i = 2;i <= n;i++)
{
if(a[i] == 0)
{
cout << i << ' ';
c++;
}
}
cout << '\n' << c;
return 0;
}
算法缺点: 有些合数被重复筛,如12被被素数2筛掉以后,又被素数3重复筛。 下面的欧拉算法克服了这一问题。
欧拉筛法
欧拉算法基于合数能写成最小素数p和另外一个数i的乘积,将合数筛掉。算法枚举所有i,将相应合数筛掉。 当 i % p == 0时,应采用下一个i,避免下一个素数,不是最小素因子。
#include <iostream>
using namespace std;
int main(int argc, char** argv)
{
int n;
int flag[10000] = {0};
int prime[10000] = {0};
int c = 0;
cin >> n;
for(int i = 2;i <= n;i++)
{
if(!flag[i])
prime[++c] = i;
for(int j = 1;j <= c && prime[j] * i <= n;j++)
{
flag[prime[j] * i] = 1;
if(i % prime[j] == 0)
break;
}
}
int s = 0;
for(int i = 2;i <= n;i++)
{
if(flag[i] == 0)
{
s++;
cout << i << ' ';
}
}
cout << '\n' << s;
return 0;
}