poj 2689 Prime Distance 二次筛法,找出给定区间所有约数
题目地址: http://poj.org/problem?id=2689
题目思路: 找出int 内所有素数空间上时不允许的,但是题目要求l ,u的差不超过100w ,在空间上还是允许的。
然后先找出5w以内的素数,这样的可以中这些素数作为合数最小的素因子将这个合数筛掉。
几个要注意的地方 【1】 因为l可能很大,j的起点不能去“p*p” 然后比L小就加一个p,想一下如果p=2,l很大会花很多时间的。 【2】 然后就是这个j 要用long long 存 ,因为我们找到的j的初值是p 的倍数中第一个大于等于L的,l很大时可能超long long。 【3】 这个筛法筛去的第一个数是4 所以1要特判 l==1 则 b[0]=1;
【4】 每次输入后要将b归零 【5】 将素数存在新的数组里面时,用数组会比用向量快得多,用向量就会超时。
代码:
#include<iostream> #include<cmath> #include<cstring> #include<cstdio> using namespace std; #define N 50000 typedef long long ll; bool p[N+5]; int prime1[N]; ll prime2[1000000]; bool b[1000010]; int nprime1=0,nprime2=0; void pre() { int len =sqrt(N); for(int i=2;i<=len;i++) if(p[i]==0) for(int j=i*i;j<=N;j+=i) p[j]=1; for(int i=2;i<=N;i++) if(p[i]==0) prime1[nprime1++]=i; } int main() { pre(); ll l,u; while(cin>>l>>u) { memset(b,0,sizeof(b)); int cnt=0; for(int i=0;i<nprime1;i++) { ll j=l/prime1[i]; while(j*prime1[i]<l||j<=1) j++; for(j=j*prime1[i];j<=u;j+=prime1[i]) { b[j-l]=1; } } if(l==1) b[0]=1; for(int i=0;i<=u-l;i++) if(b[i]==0) { prime2[cnt++]=i+l; } if(cnt>=2) { int minv=10000000; int maxv=0; ll minr,minl,maxl,maxr; for(int i=0;i<cnt-1;i++) { if(prime2[i+1]-prime2[i]<minv) { minl=prime2[i]; minr=prime2[i+1]; minv=minr-minl; } if(prime2[i+1]-prime2[i]>maxv) { maxl=prime2[i]; maxr=prime2[i+1]; maxv=maxr-maxl; } } cout<<minl<<","<<minr<<" are closest, "<<maxl<<","<<maxr<<" are most distant."<<endl; // printf("%lld,%lld are closest, %lld,%lld are most distant.\n", minl, minr, maxl, maxr); } else cout<<"There are no adjacent primes."<<endl; //printf("There are no adjacent primes.\n"); } }