问题:
求 $[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 >=1memset(ok, -1, sizeof(ok));if(l==1) ok[0]=0; //error-proneint 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;} }