素数筛法

素数筛法

埃式筛

思想

基本思想 :从2开始,将每个质数的倍数都标记成合数,以达到筛选素数的目的。

代码

const int maxn=100000005;
int prime[maxn],pnum=0;
bool p[maxn]={0};
int findprime(int n){
	for(int i=2;i<=n;i++)
	{
		if(p[i]==false){
			prime[pnum++]=i;
			for(int j=i*i;j<=n;j+=i){
				p[j]=true;
			}
		}
	}
} 

缺陷

对于一个合数,有可能被筛多次。例如 30 = 2 * 15 = 3 * 10 = 5*6……

思考

那么如何确保每个合数只被筛选一次呢?我们只要用它的最小质因子来筛选即可,这便是欧拉筛法。

欧拉筛

思想

基本思想 :在埃氏筛法的基础上,让每个合数只被它的最小质因子筛选一次,以达到不重复的目的。

代码

const int maxn=1000005;
int prime[maxn]={0},pnum=0;
bool a[maxn]={0};
void findprime(){
	pnum=0;
	for(int i=2;i<maxn;i++)
	{
		if(a[i]==0)
		{
			prime[pnum++]=i;
		}
		for(int j=0;j<pnum&&i*prime[j]<maxn;j++)
		{
			a[i*prime[j]]=true;
			if(i%prime[j]==0)
			{
				break;
			}
		}
	}
}

详解

将i的(素数)倍数都变为true,如果i能被已知素数整除,则break(因为下一个素数肯定能整除i,比如6能被2整除,也能被3整除,所以在被2整除后break),如果a[i]==0直接放入素数,每个i都需要经过第二层for循环。

  • 2是素数
    • 4(2*2)不是素数
  • 3是素数
    • 6(2*3)不是素数
    • 9(9*3)不是素数
  • 4不是素数
    • 8(4*2)不是素数(brek)
      ......
posted @ 2020-05-13 19:17  Joker-Li  阅读(65)  评论(0)    收藏  举报