题解见算法竞赛p134
技巧:
这个题l和r可能会很大,就不能用数组标记l-r内的素数,所以要加个偏移量,用l当作偏移量,则数组大小小于1e6的f[0,u-l],即可标记。
接着枚举区间中所有的相邻素数对即可。
由于1不是素数,所以对1要进行特别处理
这种处理的方式是从另一个dalao那里学来的
dalao博客:https://blog.csdn.net/a601025382s/article/details/12111297
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<queue>
#include<algorithm>
#include<vector>
#pragma warning(disable:4996)
using namespace std;
typedef long long ll;
typedef double db;
const int INF = 1e9;
const int maxn = 5e4+10;
const int maxm = 1e6 + 10;
int n,t, s;
int vis[maxn];
int prime[maxn];
void Eratosthenes(int n)
{
t = 0;
memset(vis, 0, sizeof(vis));
for (int i = 2; i <= n; i++)
{
if (!vis[i])
for (int j = i*i; j < maxn; j+=i) {
vis[j] = 1;
}
}
for (int i = 2; i < maxn; i++)if (!vis[i])prime[++t] = i;
}
int primes(int n)//O(N)
{
memset(vis, 0, sizeof(vis));//最小质因子
int m = 0;//质数数量
for (int i = 2; i <= n; i++)
{
if (vis[i] == 0)
{
vis[i] = i;
prime[++m] = i;
}//i是质数
for (int j = 1; j <= m; j++)
{
//i有比prime[j]更小的质因子,或者超出n的范围,停止循环.
if (prime[j] > i || prime[j] > n / i)break;
//prime[j]是合数i*prime[j]的最小质因数
vis[prime[j] * i] = prime[j];
}
}
return m;
}
//质因数分解
int v[maxm];
int main()
{
int l, r;
int m = sqrt(maxn+0.5);
Eratosthenes(m);
while (cin>>l>>r)
{
if (l == 1)l = 2;
memset(v,0,sizeof(v));
int x = sqrt(r);
int num = 0;
int k = 0;
for (int i = 1; i <= t; i++)
{
int a =(l-1) / prime[i]+1;
int b = r / prime[i];
for (int j = a; j <= b; j++)
{
if (j > 1)
v[prime[i] * j - l] = 1;
}
}
int mindis = INF;
int maxdis = -1;
int p=-1;
int x1, x2, y1, y2;
for (int i = 0; i <= r - l; i++)
{
if (v[i] == 0)
{
if (p == -1) {
p = i;
continue;
}
if (maxdis < i - p) {
maxdis = i - p;
x1 = p + l;
y1 = i + l;
}
if (mindis > i - p) {
mindis = i - p;
x2 = p + l;
y2 = i + l;
}
p = i;
}
}
if (maxdis == -1)cout << "There are no adjacent primes." << endl;
else cout << x2 << "," << y2 << " are closest, " << x1 << "," << y1 << " are most distant." << endl;
}
}