【学习笔记】欧拉线性筛

欧拉线性筛

简介

欧拉线性筛主要用于求\(n\)以内的所有素数,时间复杂度为\(O(n)\)

算法实现

欧拉线性筛的原理是保证\(n\)以内的所有素数只被他所含有的最小质因子筛过,这样就使得每个素数只被筛过了一次。
我们设一个数组\(prime[i]\)表示第\(i\)个素数是多少,\(is\_prime[i]\)表示第\(i\)个数是否为素数。
对于外层循环,我们枚举从1枚举到\(n\),如果当前\(i\)为素数,那么我们就把它加入到\(prime[]\)数组中。
对于当前已经出现过的素数\(prime[j]\),那么它与\(i\)的乘积就一定为合数,所以\(is\_prime[prime[j]*i]=1\)注意在枚举\(j\)时,\(j\le tot,i*prime[j]\le n\)
欧拉函数的精华

\[if(!i\%prime[j])\ break; \]

这条语句保证了所有数只被它最小的质因子筛到。
对于当前所有\(prime[j]\)筛到的数,都含有一个因数\(i\),上面这条语句一旦执行,就表示\(prime[j]\)就是\(i\)最小的质因子,我们令\(a=prime[j]\),则往后所有的\(prime[j]>a\),所以往后筛到的所有数的最小质因子都是\(a\),不用\(prime[j]\)来筛掉,所以终止循环。

模板代码

#include<bits/stdc++.h>
#define maxn 100000010
using namespace std;
int n,q,tot=0,prime[maxn];
bool isprime[maxn];
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	cin>>n>>q;
	memset(isprime,1,sizeof(isprime));
	for(int i=2;i<=n;i++){
		if(isprime[i])prime[++tot]=i;
		for(int j=1;prime[j]*i<=n&&j<=tot;j++){
			isprime[prime[j]*i]=0;
			if(i%prime[j]==0)break; 
		}
	} 
	while(q--){
		int k;
		cin>>k;
		cout<<prime[k]<<endl;
	}
	return 0;
}
posted @ 2024-09-17 13:59  SDFZ_GuoSN  阅读(13)  评论(0编辑  收藏  举报