题意:给定两个数l,r求这之间最近和最远的两个素数。数据范围是整数的上限。r-l<=10^6
分析:总思路是把l和r间的素数全部找出来,然后遍历一遍求最小距离和最大距离。用一个函数预处理数据范围内的所有素数是不现实的,一来数组不可r能开那么大二来会超时。想想素数筛的思想:用sqrt(n)以内的素数筛掉n以内的所有合数,剩下n以内的素数。这里既然预处理不可能,我们一样可以用sqrt(n)以内的素数来筛,只是这时这些素数预处理,然后每次输入l和r的时候用预处理的素数筛掉l和r之间的合数,剩下素数。sqrt(n)为2^16,也就是65536不会超时。
关键在于l,r之间的素数筛。还是用vis[]数组来做。直接用两个循环遍历 l~r 和 prim[] 估算一下应该是会超时的,所以用到一点优化技巧就是遍历l~r的时候每次加prim[i],而不是加1
代码:
#include<iostream> #include<cstring> using namespace std; long long l,r,vis[5000003],l1,l2,r1,r2,init; int prim[500005],mi,mx,cnt; void is_prim() { memset(vis,1,sizeof(vis)); cnt=0; for(int i=2;i<=50000;i++){ if(vis[i]){ prim[cnt++]=i; for(int j=2;j*i<=50000;j++) vis[j*i]=0; } } } int main() { is_prim(); while(cin>>l>>r){ for(int i=0;i<r-l+1;i++) vis[i]=1; if(l==1) vis[0]=0; for(int i=0;i<cnt&&prim[i]*prim[i]<=r;i++){ for(long long j=(long long)max((long long)(prim[i]<<1),(l+prim[i]-1)/prim[i]*prim[i]);j<=r;j+=prim[i]) vis[j-l]=0; } init=-1; mx=-1,mi=10000000; for(int i=0;i<r-l+1;i++){ if(vis[i]){ if(init!=-1){ if(mi>i-init){ mi=i-init; l1=init+l; r1=i+l; } if(mx<i-init){ mx=i-init; l2=init+l; r2=i+l; } } init=i; } } if(mx==-1) cout<<"There are no adjacent primes."<<endl; else cout<<l1<<","<<r1<<" are closest, "<<l2<<","<<r2<<" are most distant."<<endl; } }
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-11-05 14:44:14