埃氏筛与欧拉筛的实质都且就是围绕这一句话:素数的倍数不是素数。
假设要筛出n以内的素数。我们先把所有数标记为素数。枚举i从2到n,所以因为i是从小到大的,如果i
没有被前面的数(比它小的数)标记为合数,那i就是素数,加入素数列表。现在用i来筛后面的数,枚举已经筛出来的素数prime[j](j=1~cnt),标记i * prime[j]为合数,当i是prime[j]的倍数时退出循环
欧拉(Euler)筛法是用于找到从1开始,到给定的最大数之间的所有质数的一种筛法,其时间复杂度是O ( n )。
其中欧拉筛法有效地避免了埃拉托斯特尼(Eratosthenes)筛法中重复的筛选,保证了每个数只筛选一次,成功地降低了时间复杂度。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define max 100005
bool isprime[max]; //判断i是否为素数
int prime[max]; //已经筛出的素数
int n; //<= n的素数
int cnt = 0; //筛出的素数个数
void pmr()
{
memset(isprime,true,sizeof(isprime)); //全标记为素数
isprime[1] = false; //1不是素数
for(int i = 2;i <= n; ++i)
{
if(isprime[i])
{
prime[++cnt] = i; //如果i没被前面的数筛掉,则i是素数
}
for(int j = 1;j <= cnt&&i * prime[j] <= n; ++j)
{
isprime[i * prime[j]] = false; //筛掉i的素数倍,j循环枚举现在已经筛出的素数
//倍数记为合数
if(i % prime[j] == 0)
{
//如果i整除了prime[j]退出循环保证时间复杂度。
break;
}
}
}
}
int main()
{
scanf("%d",&n);
pmr();
for(int i = 1;i <= cnt;i++)
{
cout<<prime[i]<<endl;
}
}