篩質數
阿新 • • 發佈:2021-10-02
埃式篩
具體思路:用質數把質數的倍數篩掉
時間複雜度:
\((p_i為質數)\Sigma_{p_i}\frac{n}{p_i}=O(nlog(log(n)))\)(根據Mertens’ 2nd theorem)
尤拉篩
具體思路:每個合數只被其最小的質因子篩掉
實現:
void getprime(){ for(int i=2;i<=n;i++){ if(!vis[i])pri[++tot]=i; for(int j=1;j<=tot && i*pri[j]<=n;j++){ vis[pri[j]*i]=1; if(i%pri[j]==0)break; } } }
時間複雜度:\(O(n)\)
區間篩
\([L,R]\)的質數\((1\leq L \leq R \leq 2147483647 , R-L+1\leq 10^6)\)
思路:
設\(n=qp,q\leq p\)
則\(q\leq\sqrt{n}\)
所以只需要預處理\(\sqrt{R}\)的質數,再用這些質數使用埃式篩去篩[L,R]內的質數就行
//poj2689 #include<functional> #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<string> #include<cstdio> #include<cmath> #include<queue> #define ll long long using namespace std; const int maxn=1000000+101; const int MOD=1000000000+7; const int inf=2147483647; int read(){ int x=0,f=1;char ch=getchar(); for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; for(;isdigit(ch);ch=getchar())x=x*10+ch-'0'; return x*f; } int is[maxn],prime[maxn],tot; ll l,r; void get_prime(){ r=100000; for(int i=2;i<=r;i++){ if(!is[i])prime[++tot]=i; for(int j=1;j<=tot && i*prime[j]<=r;j++){ is[prime[j]*i]=1; if(!i%prime[j])break; } } return ; } int pp[maxn],cnt,si[maxn]; struct wzq{int a,b,c;}minn,maxx; void solve(){ memset(si,0,sizeof(si));cnt=0;if(l==1)si[0]=1; for(int i=1;i<=tot;i++){ int a=(l+prime[i]-1)/prime[i]; int b=r/prime[i]; for(int j=max(a,2);j<=b;j++)si[j*prime[i]-l]=1; } for(int i=0;i<=r-l;i++)if(!si[i])pp[++cnt]=i+l; if(cnt<=1){printf("There are no adjacent primes.\n");return;} minn.a=pp[1];minn.b=pp[2];minn.c=pp[2]-pp[1];maxx=minn; for(int i=2;cnt>2 && i<cnt;i++){ wzq ss;ss.a=pp[i];ss.b=pp[i+1];ss.c=ss.b-ss.a; if(ss.c>maxx.c)maxx=ss; if(ss.c<minn.c)minn=ss; } printf("%d,%d are closest, %d,%d are most distant.\n",minn.a,minn.b,maxx.a,maxx.b); } int main(){ get_prime(); while(~scanf("%lld%lld",&l,&r))solve();return 0; }