线性素数筛
每一个合数都只被它最小的素因子筛去一,筛出([1,n])中的所有素数的时间复杂度为(O(n))
int prime[maxn],cnt;
bool is_prime[maxn];
void sieve(int n){
for(int i=2;i<=n;i++){
if(is_prime[i]){
prime[cnt++]=i;
}
for(int j=0;j<cnt && 1ll*i*prime[j]<=n;j++){
is_prime[i*prime[j]]=1;
if(i%prime[j]==0) break;
}
}
}
区间素数筛
筛出区间([a,b])之内的素数,(1leq aleq bleq 1e10)
([1,b])内的合数的最小质因数一定小于等于(sqrt b),通过埃筛筛出([1,sqrt b])中的素数的同时,将其倍数从([a,b])内划去。
通过数组下标偏移记录([a,b])内的素数,也就是通过下标([0,b-a])表示下标([a,b])
const int maxn=1e8+10;
int prime[maxn];
bool is_prime1[maxn],is_prime2[maxn];
void segment_sieve(LL a,LL b){
LL t=sqrt(b),n=b-a+1;
for(int i=2;i<=t;i++) is_prime1[i]=1;
for(int i=0;i<n;i++) is_prime2[i]=1;
for(int i=2;i<=t;i++){
if(is_prime1[i]){
for(int j=2*i;j<=t;j+=i) is_prime1[j]=0;
for(LL j=max((LL)2,(a+i-1)/i)*i;j<=b;j+=i){
is_prime2[j-a]=0;
}
}
}
}