欧拉筛(最优的方法,对于找质数,细节讲解)
Posted 胜神明半子
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了欧拉筛(最优的方法,对于找质数,细节讲解)相关的知识,希望对你有一定的参考价值。
前言:最优的找质数方法,欧拉筛,看过无数博主的讲解,许多博主还是没有抓到新手的疑惑点,今天在我自身花费了一天时间不断的证明和思考,总结出来了一篇给新手的最细讲解!!!
欧拉筛
结合代码进行精准解析。
#include<iostream>
using namespace std;
bool a[100001]={1,1};//i=0,i=1的时候都不是质数 ,所以直接标记
int b[100001];//存质数
int k; long long n;
int main()
{
cin>>n;
for(int i=2;i<=100001;i++)//这个意思是在100001里面找到质数并且标记 ,质数最小是2,所以i=2
{
if (a[i]==0) b[++k]=i; //如果没有被标记为1,就是质数。我接下来会讲解为什么是质数。
for(int j=1;j<=k;j++)// //j小于当前所有的质数的个数
{
if(i*b[j]>100001)break;// 如果超出给出的范围,那么就退出循环
a[i*b[j]]=1;//用质数数依次×i,结果标记为合数(也就是标记为1)。
if(i%b[j]==0)break;//最关键的只标记一次
}
}
for(int i=1;i<=n;i++) //你想查询的个数
{int m;
cin>>m;//在100001里面输入你想查询的数
if(a[m]==0)//如果没有被标记,就是质数,直接输出。
{
cout<<m<<' ';
}
}
}
1.欧拉筛和埃氏筛法的相爱相杀。(通过上面的代码我们进行打表解析)
欧拉筛法的时间是埃氏筛法时间的十分之一甚至更少,为什么呢?
我们顺着源头思考,欧拉筛法和埃氏筛法一样,围绕{素数的倍数不是素数},
那么为什么欧拉筛比埃氏筛法效率快这么多?
欧拉筛法时间复杂度少的原因,就是它不会重复标记一个数是不是素数的倍数,例如:i = 4 ,j = 1,b[j] = 2,如果不跳出循环,b[j+1] = 3,4 * 3 = 2 * 6 = 12,在i = 6时会计算。(我打了个表,为了方便你理解)因为欧拉筛法的原理便是通过最小素因子来消除。我们可以打个表观察。欧拉筛运行打印出来的结果
i= 2//当i取2时 j =1 b[1] = 2 i*b[j] = 4 i =3//当i取3时 j=1 b[1] = 2 i*b[j] =6 j=2 b[2] = 3 i*b[j] = 9 i=4//当i取4时 j=1 b[1] = 2 i*b[j] = 8//上面提到为什么退出循环,因为如果不退出循环,就会标记一次12,所以不行 i=5//当i取5时 j=1 b[1] = 2 i*b[j] = 10 j=2 b[2] = 3 i*b[j ]=15 j=3 b[3] = 5 i*b[j] = 25 i=6//当i取6时 j=1 b[1] = 2 i*b[j] =12//这里已经标记了12了。 i=7//当i取7时 j=1 b[1] = 2 i*b[j] = 14 j=2 b[1] = 3 i*b[j] = 21 j=3 b[1] = 5 i*b[j] = 35 j=4 b[1] = 7 i*b[j] = 49
这个时候我们就会发现规律当i为偶数的时候只有标记一个值就是每次都是b[1]=2,b[1]*i=某个数,并且标记,但是当i为奇数的时候,我们则可以把所有符合的数的标记了,而不会中途退出循环,我们通过这个表可以观察,这里把2,3,5,7,11……的素数的倍数都打印出来并且标记了,在通过 if(i%b[j]==0)break;//最关键的只标记一次 ,这步,只进行一次标记,不会重复标记。
最后,如果还有地方不懂可以私信问我,我是一个热情和蔼的博主。
以上是关于欧拉筛(最优的方法,对于找质数,细节讲解)的主要内容,如果未能解决你的问题,请参考以下文章