線性篩和埃氏篩的用法及應用

埃氏篩 我的理解:每次找到一個質數,就篩掉所有他的倍數,這樣的話同一個數可能被篩掉多次,但是埃氏篩仍然有十分優越的複雜度

代碼:

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]);
	}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章