Waterloo local 1998.10.17
题目大意:给你一个区间【L,U】,求出从L到U之间素数序列中,连续两个素数差值最大
的最小的两对素数对,但其中(1<=L< U<=2,147,483,647),但区间【L,U】距离不超
过1000000
思路:因为L,U的值太大了,普通素性判断和素数筛法都不可行,所以可以考虑先筛选
一次,筛出50000以内的素数,然后用50000以内的素数再次筛选出区间【L,U】的素
数。第一次素数筛法比较简单,主要是第二次筛法,分别判断【L,U】中每个数是50000
以内的素数的多少倍,若为1倍,则从2倍开始筛选。若不为1倍,则考虑是否是整数倍,
若为整数倍,则从整数倍开始筛,否则从下1倍开始筛选
比如【L,U】为【50000,60000】,则50000为2的250000倍,应从2的25000倍筛选,
也就是50000,50002,50004,50006……筛去。
若【L,U】为【50001,60000】,则50001不为2的整数倍,应从2的250001倍筛选,也
就是50002,50004,50006……筛去。
参考博文:http://blog.csdn.net/returnzero__/article/details/7835655
#include<stdio.h> #include<string.h> bool Prime[50010]; int Primer[1000010]; bool Prime1[1000010]; int IsPrime()//第一次筛50000内的素数 { int num = 0; for(int i = 2; i <= 50000; i++) Prime[i] = true; for(int i = 2; i <= 50000; i++) { if(Prime[i]) { Primer[num++] = i; for(int j = i+i; j <= 50000; j+=i) { Prime[j] = false; } } } return num; //num为50000范围内的素数个数 } int solve(__int64 a,__int64 b) /* 在第一次筛素数的基础上,利用50000以内的素数,筛去范围【a,b】之间的素数倍数, 剩下则为素数 */ { int num = IsPrime(); memset(Prime1,true,sizeof(Prime1));//Prime1数组用来存放范围【a,b】的素性判断 if(a == 1)//这里注意1不是素数 Prime1[0] = 0; //这里表示0+1不为素数 for(__int64 i = 0; i < num && Primer[i] * Primer[i] <= b; i++) { __int64 begin = a/Primer[i] + (a%Primer[i] != 0); //上边的a/Primer算出应a为素数Primer[i]的多少倍 //(a%Primer[i]!=0)表示应从Primer[i]的a/Primer[i]倍开始筛,还是a/Primer[i]+1倍筛 if(begin == 1)//若得出结果为所被筛素数的1倍,则从该素数的2倍开始筛 begin++; for(begin = begin*Primer[i]; begin <= b; begin += Primer[i]) Prime1[begin - a] = false; } //这里重新利用Primer数组,用来存放区间【a,b】间的素数,num为素数个数 memset(Primer,0,sizeof(Primer)); num = 0; for(__int64 i = a; i <= b; i++) { if(Prime1[i-a]==1) { Primer[num++] = i-a; } } return num; } int main() { __int64 a,b; __int64 posa1,posb1,posa2,posb2; while(~scanf("%I64d%I64d",&a,&b)) { __int64 Max = -2147483647,Min = 2147483647; int num = solve(a,b); // for(__int64 i = 0; i < num; i++) // printf("%I64d ",Primer[i]+a); if(num <= 1) { printf("There are no adjacent primes.\n"); continue; } for(int i = 0; i < num-1; i++)//这里i+1范围为1到num-1,则i范围为0到num-2,之前一直错在这里 { if(Primer[i+1]-Primer[i] < Min) { Min = Primer[i+1] - Primer[i]; posa1 = Primer[i]; posb1 = Primer[i+1]; } if(Primer[i+1]-Primer[i] > Max) { Max = Primer[i+1] - Primer[i]; posa2 = Primer[i]; posb2 = Primer[i+1]; } } printf("%I64d,%I64d are closest, %I64d,%I64d are most distant.\n",posa1+a,posb1+a,posa2+a,posb2+a); } return 0; }