您的位置:首页 > 其它

POJ 2689 Prime Distance 素数筛选法应用

2014-04-21 16:06 411 查看
LINK:   http://poj.org/problem?id=2689
这是素数筛选的 进一步理解加深,可以用sqrt(m) 内的素数判断出[1,m]区间的素数 情况.
可以把 素数筛选(不需要记录下素数)的函数写成这样

for(int i=2;i<=sqrt(N)+1;i++) //for(int i=2;i<N;i++)
{
if(prime[i]) continue;
for(int j=2;j*i<N;j++) prime[i*j]=1;
}

本题,就可以先打出[1,2^16]内的素数,来判断[l,r]内素数情况,因为|r-l|<1e6 ,
即只是在[l,r]范围内用 已得到的素数 进行筛选。注意一些特殊的情况就可以了。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<cmath>
#include<queue>
#include<map>
#include<set>
using namespace std;
#define INF 1000000000
//typedef __int64 LL;
#define N ((1<<16)+100)
#define LEN 1000005
int l,r;
bool prime
,vis[LEN];
vector<int > save,ans;
void get_pri()
{
save.clear();
for(int i=2;i<N;i++)
{
if(prime[i]) continue;
save.push_back(i);
for(int j=2;j*i<N;j++) prime[j*i]=1;
}
}

int main()
{
#ifndef ONLINE_JUDGE
freopen ("in.txt" , "r" , stdin);
#endif
get_pri();
while(scanf("%d%d",&l,&r)!=EOF)
{
if(l==1) l++;//特殊处理l==1的情况
ans.clear();
memset(vis,0,sizeof(vis));
for(int i=0;i<save.size() && save[i]*save[i]<r;i++) //可以用<=sqrt(r)的素数筛选出[l,r]中的合数
{
int tmp= l/save[i]*save[i];
if(tmp<l) tmp+=save[i];
if(tmp==save[i]) tmp+=save[i];//数值较小的时候可能出现
for(int j=tmp-l;j<=r-l;j+=save[i])
vis[j]=1;
}
for(int i=0;i<=r-l;i++)
{
if(!vis[i]) ans.push_back(i+l);
}
int mi,ma,a1,b1,a2,b2;
mi=INF; ma=0;
for(int i=1;i<ans.size();i++)
{
int tmp=ans[i]-ans[i-1];
if(tmp<mi)
{
mi=tmp; a1=ans[i-1]; b1=ans[i];
}
if(tmp>ma)
{
ma=tmp; a2=ans[i-1]; b2=ans[i];
}
}
if(mi>=INF)
{
puts("There are no adjacent primes.");
}
else printf("%d,%d are closest, %d,%d are most distant.\n",a1,b1,a2,b2);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: