题意:给两个数L,U,1<=L< U<=2,147,483,647,求在L,U间的两相邻素数最小距离和最大距离。
距离的定义就是俩数相减绝对值。
The difference between L and U will not exceed 1,000,000.
解析:范围太大了,无法一次性筛出大素数,由题中L与U间范围为1000000找切入点,即筛出L与U间的素数,再O(n)扫一遍。
先筛出小素数,然后用小素数为基,筛出大素数,筛法异曲同工。
筛小素数时先假设所有数都为素数,接下来定下一个素数,此素数的倍数全不为素数。
大素数大概为8000多个,渐进复杂度 x / lnx 可以计算出来。
筛大素数时同理,先假设全为素数,接下来先由小素数的倍数扫一遍筛出不为素数的,再由余下为素数的扫一遍筛出不为素数的数。
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <map>
#include <climits>
#include <cassert>
#define LL long long
using namespace std;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
const double pi = 4 * atan(1.0);
const double ee = exp(1.0);
LL lo, hi;
const int maxs = 5e4 + 10;
LL smallPrime[maxs];
bool isSmallPrime[maxs];
int nSmallPrime;
void doSmallPrime()
{
memset(isSmallPrime, true, sizeof(isSmallPrime));
nSmallPrime = 0;
for (LL i = 2; i < maxs; i++)
{
if (isSmallPrime[i])
{
smallPrime[++nSmallPrime] = i;
for (LL j = i * i; j < maxs; j += i)
{
isSmallPrime[j] = false;
}
}
}
}
const int maxb = 1e6 + 10;
LL bigPrime[maxb];
bool isBigPrime[maxb];
int nBigPrime;
void doBigPrime()
{
memset(isBigPrime, true, sizeof(isBigPrime));
for (LL i = 1; i <= nSmallPrime; i++)
{
LL t = lo / smallPrime[i];
while (t * smallPrime[i] < lo || t <= 1)
{
t++;
}
for (LL j = t * smallPrime[i]; j <= hi; j += smallPrime[i])
{
if (lo <= j)
{
isBigPrime[j - lo] = false;
}
}
}
if (lo == 1)
isBigPrime[0] = false;
nBigPrime = 0;
for (LL i = 0; i <= hi - lo; i++)
{
if (isBigPrime[i])
{
bigPrime[++nBigPrime] = i + lo;
}
}
}
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
#endif // LOCAL
doSmallPrime();
while (scanf("%lld%lld", &lo, &hi) == 2)
{
doBigPrime();
if (nBigPrime <= 1)
printf("There are no adjacent primes.\n");
else
{
LL minn = inf, maxx = 0;
LL minl = -1, minr = -1;
LL maxl = -1, maxr = -1;
for (int i = 1; i < nBigPrime; i++)
{
if (bigPrime[i + 1] - bigPrime[i] < minn)
{
minn = bigPrime[i + 1] - bigPrime[i];
minl = bigPrime[i], minr = bigPrime[i + 1];
}
if (maxx < bigPrime[i + 1] - bigPrime[i])
{
maxx = bigPrime[i + 1] - bigPrime[i];
maxl = bigPrime[i], maxr = bigPrime[i + 1];
}
}
printf("%lld,%lld are closest, %lld,%lld are most distant.\n", minl, minr, maxl, maxr);
}
}
return 0;
}