您的位置:首页 > 其它

POJ 2689 Prime Distance【素数筛法】

2017-07-12 18:25 344 查看
题目链接

题意:求出L到R区间内相邻素数中离得最近和最远的两对。

其实就是求出L到R中的所有素数。因为数字很大,而区间最多是1e6,比较小,所以从区间着手,筛去区间中的所有合数,剩下的就是素数。筛合数可以先筛出所有的素数,再筛去他们的倍数。而数字不超过2,147,483,647,所以质因数不会超过sqrt(2,147,483,647),大约是40000多,所以用埃氏筛法筛出50000以内的所有素数,再通过这些素数筛去所有的合数,剩下的就变得很简单了。要注意对1的判断。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#define ll long long

const int INF = 0x3f3f3f3f;

bool valid[50010];
int prime[50010];
int cnt = 0;

void getPrime()
{
memset(valid, true, sizeof(valid));
for (int i = 2; i <= 50000; i++)
{
if (valid[i])	prime[++cnt] = i;
for (int j = 1; (j <= cnt) && (i * prime[j] <= 50000); j++)
{
valid[i * prime[j]] = false;
if (i % prime[j] == 0)	break;
}
}
}

int L, R;
bool notprime[1000010];
int ans[1000010];
int tot = 0;

void solve()
{
memset(notprime, false, sizeof(notprime));
if (L < 2)	L = 2;
for (int i = 1; i <= cnt; i++)
{
if (prime[i] > R)	break;
int p;
if (L % prime[i] == 0)	p = L / prime[i];
else	p = L / prime[i] + 1;
if (p == 1)	p = 2;
while (p * prime[i] >= L && p * prime[i] <= R && (ll)prime[i] * prime[i] <= (ll)R)
{
notprime[p * prime[i] - L] = true;
p++;
}
}
tot = 0;
for (int i = 0; i <= R - L; i++)
{
if (notprime[i] == false)
ans[++tot] = i + L;
}
}

int main()
{
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
getPrime();
while (scanf("%d %d", &L, &R) != EOF)
{
solve();
if (tot <= 1)
{
printf("There are no adjacent primes.\n");
continue;
}
int MIN = INF, MAX = 0;
int a, b, c, d;
for (int i = 1; i <= tot - 1; i++)
{
if (ans[i + 1] - ans[i] < MIN)
{
MIN = ans[i + 1] - ans[i];
a = ans[i];
b = ans[i + 1];
}
if (ans[i + 1] - ans[i] > MAX)
{
MAX = ans[i + 1] - ans[i];
c = ans[i];
d = ans[i + 1];
}
}
printf("%d,%d are closest, %d,%d are most distant.\n", a, b, c, d);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ACM