问题:
求 $[L, R]$ 之间的素数表
解法:
一个合数 $n$ 的最小素因子不超过 $\sqrt{n}$。
先用埃氏筛法求出 $[1,\lfloor \sqrt{R} \rfloor]$ 上的素数表
再在 $[L, R]$ 上用埃氏筛法求素数
const int N(1e5); bool isprime[N]; int prime[N]; void init(){ memset(isprime, -1, sizeof(isprime)); isprime[0]=isprime[1]=0; int np=0; for(int i=0; i<N; i++){ if(isprime[i]){ prime[np++]=i; for(int j=2*i; j<N; j+=i) isprime[j]=0; } } } typedef long long ll; const int M(1e5); bool ok[M]; int res[M]; int seive(ll l, ll r){ // l, r >=1 memset(ok, -1, sizeof(ok)); if(l==1) ok[0]=0; //error-prone int k=sqrt(r); for(int i=0; prime[i]<=k; i++){ ll j=(l+prime[i]-1)/prime*prime; j=max(j, (ll)2*prime[i]); for(; j<=r; j+=prime[i]) ok[j-l]=0; } int np=0; for(int i=0; i<=r-l; i++) if(ok[i]) res[np++]=i+(ll)l; return np; }
更新:
不必先把 $[2, \lfloor \sqrt{R} \rfloor]$ 上的素数存下来。更好的做法是先分别做好 $[2, \lfloor \sqrt{R} \rfloor]$ 和 $[L, R]$ 的表,然后从 $[2, \lfloor \sqrt{R} \rfloor]$ 的表中筛得素数的同时,也将其倍数从 $[L, R]$ 中划去。
const int N=1e6+5, M=sqrt(1e9); bool is_prime[N]; bool is_prime_small[M+1]; void segment_seive(int l, int r){ // [l,r] int t=sqrt(r); for(int i=2; i<=t; i++) is_prime_small[i]=true; for(int i=0; i<=r-l; i++) is_prime[i]=true; for(int i=2; i<=t; i++) if(is_prime_small[i]){ for(int j=2*i; j<=t; j+=i) is_prime_small[j]=false; for(int j=max(2, (l+i-1)/i)*i; j<=r; j+=i) is_prime[j-l]=false; } }