1.欧拉筛的作用
欧拉筛:可以在线性的时间复杂度内,从1~n之间的素数的集合,并且在操作过程中可以记录素数数组,为以后判断是否是素数而加快效率
和大部分的筛法一样,通过将质数的倍数标记为合数来不断筛选质数的一种方法,欧拉筛的大致思路也是这样,不够欧拉筛能实现O(n)时间复杂度的必然有他的过人之处
2.欧拉筛的代码
int pri[200005];//素数集合
int vis[200005];//判断是否是素数
int cnt=0;//统计素数数量
void ini()
{
vis[1]=1;
for(int i=2;i<=200000;i++)
{
if(vis[i]==0)
{
cnt++;
pri[cnt]=i;
}
for(int j=1;j<=cnt&&i*pri[j]<=200000;j++)
{
vis[i*pri[j]]=1;
if(i%pri[j]==0)
break;
}
}
}
思路:我们在去筛选的时候,所有位置上的标记都为0,表示所有数都为质数,但是我们知道1,不是质数,所以要给1特判,然后从2到n,如果是0,就加入到素数数组pri里面,然后就是用当前i去寻找质数倍,然后不断将这些倍数标为合数,如果i%pri[j]==0,那就直接结束循环就可以,这是保证算法为线性的关键
3.正确性的验证
我们可以假设一下,a=p*b;
p表示a的最小质因数
我们同理可以知道b小于a,那么b一定在a之前做出了判断,我们在之前就应删掉b的所有倍数,因为p为a的最小质因数,那么b的最小质因数也一定大于等于p(为什么呢?假如我们的b的最小质因数为q,并且q<p,因为a为b的倍数,a也应为q的倍数,所以q才是a的最小质因数,与条件违背,所以不符)
这样就保证了,在a被删掉之前,b一定不会结束删除他的合数,及时b的最小质因数也为p,也同样能够将a删除
4.时间复杂度的证明
我们此时需要验证一下如何判断a只会删除一次
我们可以假设a=p*b;p为最小质因数
假设p为b的最小质因数,我们由上述3可知,a一定会被b删掉一次,那么是否还能被另一个数c删除一次呢
我们继续假设a=q*c
假设c<b,那么q>p,这就说明p为c的最小质因数(为什么呢?因为a=q*c=p*b,因为p,q都为质数,那么只有c能整除p,那么按理来说在质数轮到p的时候就结束了,根本轮不到q),因此c不可能小于b
假设c>b.那么q<p,不满足题目中的条件,p为最小质因数
因此a最多只能删除1次,每个数只处理一次,时间复杂度为O(n)得证