题目:POJ-2689 Prime Distance
题目大意:给定一个区间[l,r],让求区间当中相邻素数组中距离最小的一组素数以及距离最大的一组素数。
解题思路:分析一下数据发现,虽然区间的右端点的最大值可以达到2^32左右,但是,区间的跨度确实极小的,应用这个,可以通过筛两次素数,第一次正常筛出2^16以内的素数,第二次对筛法进行区间平移,从区间的左端点开始筛除即可。这里注意左端点的处理:
1.l=(x-1)/prime[i]+1,因为x本身可能是prime[i]的倍数,若不减去1直接在最后加1可能就忽略了区间的左端点,排除这种情况先进行x-1操作。
2.(l<2)l=2,小于2第一个数就刚好是prime[i],这时从下一个数开始筛。
AC代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define maxn 100010
using namespace std;
bool visit[maxn];
int prime[maxn];
int total;
bool q[1000010];
void getprime(){
int i,j;
total=0;
memset (visit,0,sizeof(visit));
for (i=2;i<maxn;i++){
if (visit[i]==0){
prime[++total]=i;
for (j=2*i;j<maxn;j+=i){
visit[j]=1;
}
}
}
}
int main(){
int i,j,x,y;
getprime();
while (scanf("%d%d",&x,&y)!=EOF){
memset (q,0,sizeof(q));
for (i=1;i<=total&&prime[i]<=y;i++){
int l=(x-1)/prime[i]+1;
if (l<2)l=2;
int r=y/prime[i];
for (j=l;j<=r;j++){
q[j*prime[i]-x]=1;
}
}
int minn=1000100,maxx=0,pre=-1,y1,y2;
for (i=0;i<=y-x;i++){
if (q[i]==0){
if (pre!=-1){
int dis=i-pre;
if (minn>dis){
minn=dis;
y1=i;
}
if (maxx<dis){
maxx=dis;
y2=i;
}
}
if (i+x!=1)pre=i;
}
}
if (minn==1000100&&maxx==0){
printf("There are no adjacent primes.\n");
}
else {
int x1,x2;
y1+=x;
x1=y1-minn;
y2+=x;
x2=y2-maxx;
printf("%d,%d are closest, %d,%d are most distant.\n",x1,y1,x2,y2);
}
}
}