二次筛法
題目:http://poj.org/problem?id=2689
?
分析:本題數(shù)據(jù)區(qū)間的上界達(dá)到21億,不能將所有小于21億的素?cái)?shù)存下來,只能針對本題的假設(shè):區(qū)間長度小于1000000,把給定區(qū)間[ L,U ]的所有素?cái)?shù)通過篩法找出來,使用篩法篩掉[L,U]區(qū)間的所有非素?cái)?shù),需要知道[L,U]區(qū)間的所有非素?cái)?shù)的素?cái)?shù)因子(因?yàn)橐粋€(gè)非素?cái)?shù)是被它的最小素?cái)?shù)因子篩掉),2147483647內(nèi)的數(shù)或者是素?cái)?shù),或者能被sqrt(2147483647)內(nèi)的素?cái)?shù)整除,也就是說,[L,U]區(qū)間的所有非素?cái)?shù)的素?cái)?shù)因子都在sqrt(2147483647)內(nèi),預(yù)先將sqrt(2147483647)內(nèi)的所有素?cái)?shù)找出來,然后用這些素?cái)?shù)去篩掉指定區(qū)間的所有非素?cái)?shù)。
?
代碼:
#include <stdio.h> #include <string.h> #define N 50001 #define INF 99999999 long long prime1[N+2],nprime1; bool isprime[20*N+2]; void make_prime1() {long long i,j;nprime1=0;memset(isprime,1,sizeof(isprime));for(i=2;i<N;i++){if(isprime[i]){nprime1++;prime1[nprime1]=i;for(j=i*i;j<N;j+=i){isprime[j]=0;}}} } long long L,U; long long prime2[1000001]; long long nprime2; void make_prime2() {long long i,j,b;memset(isprime,1,sizeof(isprime));for(i=1;i<=nprime1;i++){b=L/prime1[i];while(b*prime1[i]<L||b<=1)b++;for(j=b*prime1[i];j<=U;j+=prime1[i]){if(j>=L){isprime[j-L]=0;}}if(L==1){isprime[0]=0;}} }void solve() {long long i;long long min=INF,max=-INF;long long minl,minr,maxl,maxr;make_prime2();nprime2=0;for(i=0;i<=U-L;i++){if(isprime[i]){nprime2++;prime2[nprime2]=i+L;}}if(nprime2<=1){printf("There are no adjacent primes.\n");}else{for(i=1;i<nprime2;i++){if(prime2[i+1]-prime2[i]<min){min=prime2[i+1]-prime2[i];minl=prime2[i];minr=prime2[i+1];}if(prime2[i+1]-prime2[i]>max){max=prime2[i+1]-prime2[i];maxl=prime2[i];maxr=prime2[i+1];}}printf("%I64d,%I64d are closest, %I64d,%I64d are most distant.\n",minl,minr,maxl,maxr);} } int main() {make_prime1();while(~scanf("%I64d%I64d",&L,&U)){solve();}return 0; }
?
總結(jié)