标签:
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 13459 | Accepted: 3578 |
Description
Input
Output
Sample Input
2 17 14 17
Sample Output
2,3 are closest, 7,11 are most distant. There are no adjacent primes.
Source
思路:http://blog.csdn.net/a601025382s/article/details/12111297
题意:输入区间[l,u],其中l和u为int范围的整数,区间最大为1000000。求出[l,u]中,相邻素数只差最大和最小的素数对。当存在多个时,输出较小的素数对。
题解:l,u范围太大,不能直接求int范围的素数。而区间间隔比较小,只有1e6,而且对于int范围内的合数来说,最小质因子必定小于2^16。所以可以求出[l,u]中合数,转而求出素数,然后暴力枚举所有素数对即可。
如何求区间[l,u]中的合数:上面已经说了,合数的最小质因子小于2^16,即小于50000。所以先求出小于50000的所有素数。则区间[l,u]中的合数,必定可以表示为小于50000的素数的倍数。对于素数p来说,令a=(l-1)/p+1,b=u/p。则枚举j=a到b,j*p可以枚举所有[l,u]中质因子含有p的合数。枚举所有小于50000的素数,然后用上述方式枚举倍数,即可找出[l,u]中所有的合数。
由于l,u在int范围,所以不能直接用数组标记。需要加个偏移量,取l,则数组大小小于1e6的f[0,u-l],即可标记。
接着枚举区间中所有的相邻素数对即可。
特别注意:由于1不是小于50000的素数的倍数,所以在与合数相斥中,会被当成素数。需要特别处理下。
ac代码#include<stdio.h> #include<string.h> #include<math.h> int is[50010],prime[50010],f[1000010]; __int64 l,u; int k; void fun() { int i,j; k=0; for(i=2;i<50010;i++) { if(!is[i]) { prime[k++]=i; for(j=i+i;j<50010;j+=i) { is[j]=1; } } } } int main() { fun(); while(scanf("%I64d%I64d",&l,&u)!=EOF) { if(l==1) l=2; int i,j,a,b; memset(f,0,sizeof(f)); for(i=0;i<k;i++) { a=(l-1)/prime[i]+1; b=u/prime[i]; for(j=a;j<=b;j++) { if(j>1) { f[j*prime[i]-l]=1; } } } int p=-1,maxn=-1,minn=1<<30,x1,x2,y1,y2; for(i=0;i<=(u-l);i++) { if(f[i]==0) { if(p==-1) { p=i; continue; } if(maxn<i-p) { maxn=i-p; x1=p+l; y1=i+l; } if(minn>i-p) { minn=i-p; x2=p+l; y2=i+l; } p=i; } } if(maxn==-1) { printf("There are no adjacent primes.\n"); } else printf("%d,%d are closest, %d,%d are most distant.\n",x2,y2,x1,y1); } }
POJ题目2689 Prime Distance(任何区间素数筛选)
标签:
原文地址:http://blog.csdn.net/yu_ch_sh/article/details/45932903