【题解】质数距离

N4Ig5iBcoKZaAXKBtUBLKI0FoBKIAaEAB0wFYBOAZgDYB2AOgBYqAmCmgBm55sJACOmKiAC+BdJgAKefkMggR4yQoAeAWTESsmAE5zMFLSpABlWUXkgmxnQoCGFwZhvK7IACZOrr7RgUAzt4utv7gwQq+JgBiEdahmADqcVHuAKIGCmQJCsQpOSC4+W5hACrFfpimAMKZINklmDAVJgA2cQ2VCpqWmACMBdUA8nUDjQoAIvykCnR9rAAcC4xUnBTrCwUeYgC6RABGKHsgAMYoJme9CmNdIAAaA1cgNyYAZqMFiY/O1wUAtj0fs8CidAVYXu4YGD+rsiAEoAhdABXGDiEDvaAgeGQVDuTh1Mj4ohIX5EAB2mEAJUaAa2VAAxB/D+5xAjIUrX42NYRDZkD6TDcLJA0XZUD6XJFfO0Avswp5Yp5fOOAHdyPjxsDiTDyZhAL8BgHnEhlMgVsuFQTkgbm8/mYIUm2Xm8VWhwy0X2+WiY5WMjfZVZCFhVj8EnqkAUhSAblNAN+KAApAFTmgBjtQAIRgBKA040ACiC2s0WiXp63OuWWyWYeG2l0593uoj6SCIlFon2gblms6YgAWJYQ9n0WoUAElWn8YGSPAACUyK7uMwu23FhCjYIkgIPfUMgGn0ogs3FGguuvqcR1mPcWw/Fp1ZwuHj2YViq44ALyZrbrMGrpqIPtYbhfyNR2l/FF3ztH0+h/BE/2Al1QPA2tIJAGtoJFWDX2AqhPygKgUL/bCgIQj8QC/XC33wyB0MIzDiKogCILwmtyJ9LCaLguiRQwnliOAs0iOY1DSKQjjePg+j2KY0BAP/cTaJIxD2LAoT6wUmSCJ4qSWMk05pKguTOP4nSlO0ijBLU19dJrbjTTMzDRKssibKU2yLMgb8HIMvSjPkkzhLYjzHPYlyvMUwLlOc/zqOCwyYLckSjLEzT1LQ+yItIhjKOinyouCvyjIC+LXnsVoAhCl1sTnQxFwAYiYGwNVJEMqTpVMd0wY0sR808j1ME8RTPPMLza0L92vJ52FheqFFG/S1PywqQtSsjYJmorIuQ5ilo01t1sWgrltIpzcs2nbiqmvKjpW4zTtmxLYu2q6UqSy7dvMsK1rO9zMsekL9tuoqfo2qAtteu6YsYv6uJe6ajr+sH3tWyHgYyuHPuu0Ggd+tGvoh5HYYuw7ZuhjHwZymHZN8wn7pu8mQbS+H0dpzHiapxHcYBt7SY+vG6ex57GfplGae5lTLIxknmc8wWQKRzm5oe6XRcllnIHW/mFqZuzKb5vaselonVM+gnNfZqXWYRhXxZ1nHzZN37jlbaqDg7VWQwAexJZWQFUaS0RrUAazKhRpxAJEtKBeYqDIGg2AYOgaFYLhODobJqxmQk1UuIOQ6sKg+ioBY+hoBgKE4fPw7jgNk6gVPbmlIhg4SoFs4ThYGBoJhCSoCg6DWb5dBT3rIX4Ou+OlNN3AAGQKXQYHeKsgUJJde8r/uwneWuQ8XyAq5MP5viH+CR/9kAACE6iYTY1Qnp5XBvLIlxZPrD9IJ4xh2b2+7T3eQ4PkwT6eMhUjCJfOeY0rBcFTA/V+FdN7LyaJ/eu393C/yBPQAoQDQGT2niAzAXdwHMiOG/Jeap7BwOHkyMISCrCjQvnUAMaop4zxvooO+8A8E4kgQhd+txXgkP3mQzAFDsG0NuGgzA59bj0KwQoBYzDMTbnYRvLe7g2ylgzvXcEdBWAMAThwZYScOGENuH8bYa81G3lYJo+geiFEwIUCcYxqi+KUL6IwL0rArGcJMKYHheEEHkNGEYahz8MEMJGjIiBBDoFqlMFIQe68PHuAeLE+BfCFACImqqYRHw6GYNnpQsJrDkDyPiWEO4MSTF8WsWqL4STSGjz8X/MRJgREKD4NkkJyCjBbhYXIiJiiwhTHKbwupmAJ5tMkSATgDBVg8BmbM7gNV9GRNuBSQZdFimYABDUoZh80kgCESYCRuTbz8EqbcUEWyfEpOPjQ4J4zy6LL6U0QEe9LnDNSTcsZRyJonPfuw7EwA0QzEQFATgs52HbExBCkwHga4PMPGiEeoBfEbL6E/VhXAP5opZBi24MBUWphxW8fFXTICEvcMQrFUAyVhC8ZS0lNiQBfDpdSzADxmUMp3vgElLLbF9C5eihleL+XYoZdw4VVKGXEPFfSqJfKCUMq+NKnl9w5Xco5X0QEIqP6aolWqPFOqZVcI1fKohxq1WyoNcqr4lqGUPBtWqaISqOXqCdWnF1JrcXuvNbcDQrrbgBC9QKtUaBVVBtuG2PoYBvhavDZG+5MaTARrACIb1ia+h9AAPrRt1bGzN8ac1pszSmsNibWD7GzYa0t+x82VqUWW4tCb3CvFaLCxtNKACeABBD1Jg0idptVubkfEkQWiIPYDEgMTATDSPa24phEjdtTe4BAMA/UmACCcNd7gAgBC3WEfYu6e1KLIOWo9YQ2wnprcqi9+wG26uONyeFRBnYsJeSRNcG60DDgQGgV4aB07Yj4hCvijsaAkpdP4PiMx3Y+j4m7NmX9M4h0OPXCAWR+AAGtrYkQkkQAAbthogE63pwCVm9dtmAACaztg5ogtJQOgidI7VXYGQUQQA=

题目描述

题目描述
给定两个整数 ,求闭区间 [ L , R ] [L,R] [L,R]中相邻两个质数差值最小的数对与差值最大的数对。当存在多个时,输出靠前的素数对。

输入格式
多组数据。每行两个数 L , R L,R L,R
输出格式
详见输出样例。

样例

样例输入
2 17
14 17
样例输出
2,3 are closest, 7,11 are most distant.
There are no adjacent primes.

题目分析

这一道题很明显是素数筛的题,一般做素数筛都用线筛,因为要快一些,这道题也一样。

直接每一次用线筛,筛出在 [ L , R ] [L,R] [L,R]这个区间的所有质数,然后再进行枚举比较求出间隔最小与间隔最大的相邻质数。

错误代码

#include 
#include 
#include 
#include 
using namespace std;
const int M = 1e8 + 5;
bool flag[M];
int pre[M];
int prime(int l, int r) {
    memset(flag, false, sizeof(flag));
    memset(pre, 0, sizeof(pre));
    int k = 0;
    if (l == 1) {
        l++;
    }
    for (int i = 2; i <= r; i++) {
        if (!flag[i]) {
            k++;
            pre[k] = i;
        }
        for (int j = 1; j <= k && pre[j] * i <= r; j++) {
            flag[pre[j] * i] = true;
            if (i % pre[j] == 0)
                break;
        }
    }
    return k;
    //	for(int i=1;i<=k;i++){
    //		printf("%d ",pre[i]);
    //	}
}
int main() {
    int L, R;
    while (scanf("%d %d", &L, &R) != EOF) {
        int len = prime(L, R);
        if (len == 1) {
            printf("There are no adjacent primes.\n");
        }
        int x1 = 0, x2 = 0, y1 = 0, y2 = 0;
        int minn = 0x3f3f3f3f, maxn = 0;
        for (int i = 1; i <= len - 1; i++) {
            if (pre[i + 1] - pre[i] < minn && pre[i] >= L) {
                x1 = i, x2 = i + 1;
                minn = pre[i + 1] - pre[i];
            }
            if (pre[i + 1] - pre[i] > maxn && pre[i] >= L) {
                y1 = i, y2 = i + 1;
                maxn = pre[i + 1] - pre[i];
            }
        }
        if (x1 == 0 && x2 == 0 && y1 == 0 && y2 == 0) {
            printf("There are no adjacent primes.\n");
            continue;
        }
        printf("%d,%d are closest, %d,%d are most distant.\n", pre[x1], pre[x2], pre[y1], pre[y2]);
    }
    return 0;
}

但是一提交就直接超时爆零了。
在这里插入图片描述
之后我就反思为何会超时。首先,主函数里遍历答案这是不可去除的;之后就是线筛函数也不会错。最后,我发现在每次输入 L , R L,R L,R之后,都有一次线筛,那万一第一个数据都包含了之后的数据,就不是浪费时间了。

所以我们可以找到数据的极值,即 M M M。在每次输入数据之前都进行一次最大的线筛,则后面的数据就直接使用就可以了。

正确代码

#include
#include
#include
using namespace std;
const int M=1e7+5;
bool flag[M],flag1[M];
int pre[M],arr[M];
int k;
void Prime2(){
	flag[0]=flag[1]=true;
	for(int i=2;i<=M;i++){
		if(flag[i]==false){
			pre[k++]=i;
		}
		for(int j=1;j<k&&pre[j]*i<M;j++){
			flag[pre[j]*i]=true;
		}
	}
}
int main(){
	int L,R;
	Prime2();
	while(scanf("%d %d",&L,&R)!=EOF){
		if(L==1){
			L=2;
		}
		memset(flag1,false,sizeof(flag1));
		for(int i=0;i<k;i++){
			int a=(L-1)/pre[i]+1;
			int b=R/pre[i];
			for(int j=a;j<=b;j++){
				if(j>1){
					flag1[pre[i]*j-L]=true;
				}
			}
		}
		int x1=0,x2=0,y1=0,y2=0;
		int minn=0x3f3f3f3f,maxn=-1,p=-1;
		for(int i=0;i<=R-L;i++){
			if(flag1[i]==false){
				if(p==-1){
					p=i;
					continue;
				}
				if(i-p<minn){
					x1=p+L,x2=i+L;
					minn=i-p;
				}
				if(i-p>maxn){
					y1=p+L,y2=i+L;
					maxn=i-p;
				}
				p=i;
			}
		}
		if(maxn==-1){
			printf("There are no adjacent primes.\n");
			continue;
		}
		printf("%d,%d are closest, %d,%d are most distant.\n",x1,x2,y1,y2);
	}
	return 0;
}

在这里插入图片描述

你可能感兴趣的:(数论,素数筛,算法,素数筛)