POJ2689 Prime Distance


题目链接

知识点:质数筛、优化

题意

l l l r r r区间内所有的质数中相邻质数之差绝对值最大和最小值,并输出答案相同时质数小的质数

思路

1 到 2 31 的 质 数 筛 M L E , 注 意 到 区 间 长 度 不 超 过 1 6 1到2^{31}的质数筛MLE,注意到区间长度不超过1^6 1231MLE16
预 处 理 出 不 超 过 2 31 的 质 数 筛 , 然 后 用 这 些 质 数 推 出 l 到 r 范 围 内 的 质 数 预处理出不超过\sqrt{2^{31}}的质数筛,然后用这些质数推出l到r范围内的质数 231 lr
存 储 l 到 r 范 围 内 的 质 数 把 l 的 下 标 设 为 0 , r 的 下 标 为 r − l 存储l到r范围内的质数把l的下标设为0,r的下标为r-l lrl0rrl
实现思路见代码。

代码

#include"cstdio"
#include"vector"
#include"bitset"
#include"algorithm"

#define ll long long
#define vec vector<ll>
#define pb push_back
#define all(a) (a).begin(),(a).end()
const ll N=2e5+10,M=1e6+10;
using namespace std;

vec preprime;//sqrt(1<<31)范围内的质数
bitset<M> notprime;
vec prime,dis;//prime:l到r的质数,dis:l到r的质数中相邻质数的距离

//预处理sqrt(1<<31)范围内的质数
void getprime() {
   
  for(ll i=2; i<N; i++) {
   
    if(!notprime[i]) preprime.pb(i);
    for(ll j=0; j<preprime.size()&&i*preprime[j]<N; j++) {
   
      notprime[i*preprime[j]]=true;
      if(i%preprime[j]==0) break;
    }
  }
}

int main() {
   
  ll l,r;
  getprime();
  while(~scanf("%lld%lld",&l,&r)) {
   
    prime.resize(0);
    notprime.reset();
    if(l==1) notprime[0]=true;//区间包含1,1不是质数
    //枚举sqrt(1<<31)范围内的质数,preprime[i]*preprime[i]解释见for内的注释,
    //preprime[i]*preprime[i]>r时更大的质数没有贡献
    for(int i=0; i<preprime.size()&&preprime[i]*preprime[i]<=r; i++) {
   
      //枚举第i个质数的j倍;对于小于preprime[i]的倍数,交换质数和倍数的含义,
      //发现之前已经枚举过了;(l-1)/preprime[i]+1 是 l/preprime[i] 的向上取整,
      //最小的倍数;r/preprime[i]:最大的倍数
      for(int j=max(preprime[i],(l-1)/preprime[i]+1); j<=r/preprime[i]; j++) {
   
        notprime[j*preprime[i]-l]=true;
      }
    }
    //筛出l到r的质数
    for(int i=0; i<=r-l; i++) {
   
      if(!notprime[i]) {
   
        prime.pb(i+l);//记得还原
      }
    }
    if(prime.size()<2) {
   
      printf("There are no adjacent primes.\n");
      continue;
    }
    dis.resize(prime.size()-1);
    //计算距离
    for(int i=0; i<prime.size()-1; i++) dis[i]=prime[i+1]-prime[i];
    ll minans=dis[0],maxans=dis[0];
    ll minindex,maxindex;
    minindex=maxindex=0;
    for(int i=0; i<dis.size(); i++) {
   
      if(dis[i]<minans) {
   
        minans=dis[minindex=i];
      }
      if(dis[i]>maxans) {
   
        maxans=dis[maxindex=i];
      }
    }
    printf("%lld,%lld are closest, %lld,%lld are most distant.\n",
    prime[minindex],prime[minindex+1],prime[maxindex],prime[maxindex+1]);
  }
  return 0;
}
全部评论

相关推荐

冲芭芭拉鸭:你这图还挺新,偷了。
投递美团等公司10个岗位
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务