现在的位置: 首页 > 综合 > 正文

POJ 2688 Prime Distance

2019年04月08日 ⁄ 综合 ⁄ 共 1429字 ⁄ 字号 评论关闭

大意不再赘述。

思路:本题数据区间的上下界到达21亿,所以数组是存不下来的。只能针对本题的假设:区间的长度小于1000000,然后把区间[L,U]内的素数筛选出来。

具体怎么去筛选,我们知道,2147483647内的数要么是素数,要么可以被sqrt(2147483647)内的素数整除,也就是说,[L,U]区间内所有的非素数的所有素数因子都在sqrt(2147483647)内。

首先将sqrt(2147483647)所有的素数筛选出来,然后用这些素数去筛选区间[L,U]内的非素数。

注意一些细节问题,如把is_prime[0] = 1,因为1不是素数。

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;

typedef long long LL;

const int MAXN = 46341; //(int)sqrt(INT_MAX+0.5)+1;
const int INF = 0x3f3f3f3f;

LL L, U;

bool vis[MAXN];
int prime[MAXN];
int tot1;

bool is_prime[1000010];
LL prime2[1000010];
int tot2;

void init()
{
	tot1 = 0;
	memset(vis, 0, sizeof(vis));
	for(LL i = 2; i < MAXN; i++) if(!vis[i])
	{
		prime[tot1++] = i;
		for(LL j = i*i; j < MAXN; j += i) vis[j] = 1;
	}
}

void do_prime()
{
	memset(is_prime, 0, sizeof(is_prime));
	for(int i = 0; i < tot1; i++)
	{
		LL b = L / prime[i];
		while(b * prime[i] < L || b <= 1) b++; //1、取在L的右边,离L最近的非素数。2、L本身在已经预处理出来的素数的范围内。 
		for(LL j = b * prime[i]; j <= U; j += prime[i])
		{
			if(j >= L) is_prime[j-L] = 1;
		}
	}
	if(L == 1) is_prime[0] = 1; //L为1时的边界 
	tot2 = 0;
	for(LL i = 0; i <= U-L; i++) if(!is_prime[i])
	{
		prime2[tot2++] = i+L;
	}
}

void solve()
{
	init();
	do_prime();
	if(tot2 <= 1)  { printf("There are no adjacent primes.\n"); return ; }
	LL min = INF, max = -INF, minl = 0, minr = 0, maxl = 0, maxr = 0;
	for(int i = 1; i < tot2; i++)
	{
		LL dif = prime2[i] - prime2[i-1];
		if(min > dif)
		{
			min = dif;
			minl = prime2[i-1], minr = prime2[i];
		}
		if(max < dif)
		{
			max = dif;
			maxl = prime2[i-1], maxr = prime2[i];
		}
	}
	printf("%lld,%lld are closest, %lld,%lld are most distant.\n", minl, minr, maxl, maxr);
}

int main()
{
	while(~scanf("%lld%lld", &L, &U))
	{
		solve();
	}
	return 0;
}

抱歉!评论已关闭.