筛质数
埃式筛
具体思路:用质数把质数的倍数筛掉
时间复杂度:
\((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;
}
质因数分解
先预处理\(\sqrt{n}\)内的质数,用这些去除尽n
对于n中大于\(\sqrt{n}\)的质数至多有一个,最后再判断就行