埃氏篩 我的理解:每次找到一個質數,就篩掉所有他的倍數,這樣的話同一個數可能被篩掉多次,但是埃氏篩仍然有十分優越的複雜度
代碼:
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]);
}
}