线性筛和埃氏筛的用法及应用

埃氏筛 我的理解:每次找到一个质数,就筛掉所有他的倍数,这样的话同一个数可能被筛掉多次,但是埃氏筛仍然有十分优越的复杂度

代码:

inline void get_prime(){
	bool limit[N];
	limit[0]=limit[1]=true;
	for(int i=2;i<=n;i++){
		if(!limit[i]){
			prime[++cnt]=i;
			for(int j=i*2;j<=n;j+=i)
				limit[j]=true;
		}
	}
}

欧拉筛(线性筛):只用该合数的最小质数因子筛去这个数,所以一个数最多被筛掉一次,复杂度较前者更优

代码:

inline void oula_get_prime(){
	bool limit[N];
	limit[0]=limit[1]=true;
	for(int i=2;i<=n;i++){
		if(!limit[i])
			prime[++cnt]=i;
		for(int j=1;j<=cnt&&prime[j]*i<=n;j++){
			limit[prime[j]*i]=true;
			if(i%prime[j]==0)
				break;//如果i已经是prime[j]的倍数,那么就可以退出了
		}
	}
}

洛谷 P1865 

求区间质数个数

输入格式:

一行两个整数 询问次数n,范围m

接下来n行,每行两个整数 l,r 表示区间

输出格式:

对于每次询问输出个数 t,如l或r∉[1,m]输出 Crossing the line

欧拉筛裸题 找完素数后用num[i]维护一下从1~i之间的素数个数就可以了

#include<bits/stdc++.h>
#define N 1000010
using namespace std;
int n,m,num[N],l,r,prime[N],cnt;
bool limit[N];
inline void get_prime(){
	limit[0] =limit[1]=true;
	for(int i=2;i<=m;i++){
		if(!limit[i])
			prime[++cnt]=i;
		for(int j=1;j<=cnt&&prime[j]*i<=m;j++){
			limit[prime[j]*i]=1;
			if(i%prime[j]==0){
				break;
			}
		}
	}
}
int main(){
	scanf("%d%d",&n,&m);
	get_prime();
	for(int i=1;i<=m;i++){
		if(!limit[i])
			num[i]=num[i-1]+1;
		else
			num[i]=num[i-1];
	}
	while(n--){
		scanf("%d%d",&l,&r);
		if(l<1||r>m)
			puts("Crossing the line");
		else
			printf("%d\n",num[r]-num[l-1]);
	}
}

阅读更多

没有更多推荐了,返回首页