题解 PK2689 【质数距离】


PK2689 质数距离

题目大意:

solution:

由于数据范围,直接筛质数是不被允许的。考虑 \(r-l\) 较小,所以从这下手。我们可以先筛出一些质数,然后用这些质数来筛掉 \(l\)\(r\) 合数,打上标记,剩下的即为质数。
有了思路,下面看细节。

细节处理:

  • 我们设 \(x\times pr_i\) 为大于等于 \(l\) 的最小数, \(y\times pr_i\) 为小于等于 \(r\) 的最大数。求出 \(x,y\) 。易得 \(x=\lceil {\frac{l}{pr_i}}\rceil\) , \(y=\lfloor {\frac{r}{pr_i}}\rfloor\),质数是默认向下取整的,为了快速向上取整,把它转化为 \(x=\lfloor{\frac{l+pr_i-1}{pr_i}}\rfloor\)
  • 多组数据别忘了初始化。
代码
#include
#include
#include
#define int long long
using namespace std;
const int N=1e6+5,Q=1e5+5;
int pr[Q],cnt; bool vis[N];
inline void xxs(){//筛了5e4
    for(int i=2;i<=50000;i++){
        if(!vis[i]) pr[++cnt]=i;
        for(int j=1;j<=cnt;j++){
            if(i*pr[j]>50000) break;
            vis[i*pr[j]]=1;
            if(i%pr[j]==0) break;
        }
    }
}
const int LR=1e6+5;
bool vis2[LR];
signed main(){
    xxs();
    int l,r;
    while(scanf("%lld%lld",&l,&r)!=EOF){
        memset(vis2,0,sizeof(vis2));//初始化合数标记
        
        for(int i=1;i<=cnt;i++){
            int x=(l+pr[i]-1)/pr[i],y=r/pr[i];//确定x,y
            for(int j=x;j<=y;j++){
            	int s=pr[i]*j;
                if(j>1&&s>=1) vis2[s-l]=1;//标记整体往左移了l,保证能存下
            }
        }
        int mx1=0,mx2=0,mn1=0,mn2=0x7fffffff;
        bool flag1=0,flag2=0;
        int p1,p2;
        for(long long i=l;i<=r;i++){
        	if(i==1) continue;
            if(!vis2[i-l]&&!flag1){
                p1=i,flag1=1; 
                continue;
            }
            if(!vis2[i-l]){
                flag2=1;
                p2=i;
                if(p2-p1>mx2-mx1) mx1=p1,mx2=p2;
                if(p2-p1

End