埃氏筛 我的理解:每次找到一个质数,就筛掉所有他的倍数,这样的话同一个数可能被筛掉多次,但是埃氏筛仍然有十分优越的复杂度
代码:
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]);
}
}