筛质数

埃式筛

具体思路:用质数把质数的倍数筛掉
时间复杂度:
((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])的质数((1leq L leq R leq 2147483647 , R-L+1leq 10^6))
思路:
(n=qp,qleq p)
(qleqsqrt{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.
");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.
",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})的质数至多有一个,最后再判断就行

原文地址:https://www.cnblogs.com/hh--boke/p/15362052.html