素数的两种筛法

介绍两种筛法

第一种:埃拉托斯特尼(Eratosthenes)筛法
简称:普通筛或埃氏筛

时间复杂度:O(nloglogn)

下面上普通筛法的两种写法及优化

写法1:

#include<bits/stdc++.h>
using namespace std;
const int N=1e5;
int a[N];
void ss(int n){
	memset(a,-1,sizeof(a));//a[i]=-1 先假定所有数都为素数,i是素数a[i]=-1,不是素数a[i]=0 
	a[0]=a[1]=0;
	for(int i=2;i<=n;i++)
		if(a[i])
		for(int j=i*2;j<=n;j+=i) a[j]=0; //从i*2,开始以他自身为倍数相加的数都是合数 
}
int main(){
	int n;
	while(cin>>n){
		ss(n); 
		for(int i=2;i<=n;i++)
			if(a[i]) cout<<i<<endl;
	}
} 

写法2:最后一个for循环可以改写一下
实质一样。

void ss(int n){
	memset(a,-1,sizeof(a));
	a[0]=a[1]=0;
	for(int i=2;i<=n;i++)
		if(a[i])
		for(int j=2;j*i<=n;j++) a[i*j]=0; 
}

两处优化,上代码。

void ss(int n){
	memset(a,-1,sizeof(a));
	a[0]=a[1]=0;
	for(int i=2;i<=sqrt(n);i++)//优化1:只需要到sqrt(n) 
		if(a[i])
		for(int j=i*i;j<=n;j+=i) a[j]=0; //j从i*i开始 
}

第二种:欧拉筛法。

时间复杂度:O(n)
原理与普通筛类似,只是避免了重复筛同一个合数
下面上代码

const int N=1e5;
bool a[N];
void Ess(int n){
	 memset(a,true,sizeof(a));
	 int p[N],cnt=0;
	 for(int i=2;i<=n;i++)
	 {
	 	if(a[i]) p[cnt++]=i;
	 	for(int j=0;j<cnt&&i*p[j]<=n;j++)//每个合数只用其最小质因数去筛 
	 	{
	 		a[i*p[j]]=false;
	 		if(i%p[j]==0) break; 
		}//如果i能被p[j]整除,说明i*p[j+1]已经被筛过,因为i是p[j]的倍数,所以i*[p+1]是p[j]的倍数 
	 } 
} 

注意以上两种筛法1都要特判,
如果题目给的范围还有需要将1特判

----定理-----:任意大于1的整数的最小因数是素数。
而且对合数进行筛选时,它的所有因数一定都被筛过了。

看完以上两种素数筛法:去洛谷练练手,
题目传送门:模板题

全部评论

相关推荐

美团 后端开发 总包n(15%是股票)
点赞 评论 收藏
分享
沉淀一会:1.同学你面试评价不错,概率很大,请耐心等待; 2.你的排名比较靠前,不要担心,耐心等待; 3.问题不大,正在审批,不要着急签其他公司,等等我们! 4.预计9月中下旬,安心过节; 5.下周会有结果,请耐心等待下; 6.可能国庆节前后,一有结果我马上通知你; 7.预计10月中旬,再坚持一下; 8.正在走流程,就这两天了; 9.同学,结果我也不知道,你如果查到了也告诉我一声; 10.同学你出线不明朗,建议签其他公司保底! 11.同学你找了哪些公司,我也在找工作。
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务