http://poj.org/problem?id=2689
题意:
给定一个范围[l,r]求区间[l,r]中距离最近的一对素数和距离最远的一对素数,l,r的值非常打,但是区间比较小,大概在100w左右。
思路:
这题只能采用素数筛法了,但是由于l,r的值实在太大,开不了如此大的空间。但是[l,r]区间长度比较小,我们换个思路,先把2到根号r范围内的素数筛出来,打个表,这样一来,[l,r]区间内的质因子数都在表中了,再筛一次,就能求得[l,r]区间内的素数表,还挺难写的。。。。
代码:
#include <cstdio>
#include <cstring>
#define LL long long
using namespace std;
int prime1[1000000 + 10],prime2[1000000 + 10];
bool f[1000000 + 10];
void getPrime(int n)
{
prime1[0] = 0;
memset(f, true, sizeof(f));
for(int i = 2; i <= n; i++)
{
if(f[i])
{
prime1[0]++;
prime1[prime1[0]] = i;
//printf("%d %d\n", i, n);
}
for(int j = 1; ((j <= prime1[0]) && (i * prime1[j] <= n)); j++)
{
f[i * prime1[j]] = false;
if(i % prime1[j] == 0)
break;
}
}
}
void Prime(int l, int r)
{
if(l == 1) l = 2;
memset(f, true, sizeof(f));
for(int i = 1; (i <= prime1[0]) && (LL)prime1[i] * prime1[i] <= r; i++)
{
int x = l / prime1[i] + (l % prime1[i] > 0);
if(x == 1) x = 2;
for(int j = x; (LL)j * prime1[i] <= r; j++)
if((LL)j*prime1[i] >= l)
f[j*prime1[i] - l] = false;
}
prime2[0] = 0;
for(int i = 0; i <= r - l; i++)
if(f[i])
{
//printf("%d\n", i + l);
prime2[++prime2[0]] = i + l;
}
if(prime2[0] < 2)
{
printf("There are no adjacent primes.\n");
return;
}
else
{
int x1 = 0, x2 = 0, y1 = 0, y2 = 1000000 + 10;
// for(int i = 1; i <= prime2[0]; i++)
// printf("%d\n", prime2[i]);
for(int i = 2; i <= prime2[0]; i++)
{
if(prime2[i] - prime2[i - 1] > x2 - x1)
{
x2 = prime2[i];
x1 = prime2[i - 1];
}
if(prime2[i] - prime2[i - 1] < y2 - y1)
{
y2 = prime2[i];
y1 = prime2[i - 1];
}
}
printf("%d,%d are closest, %d,%d are most distant.\n", y1, y2, x1, x2);
}
}
int main()
{
int l,r;
getPrime(50000);
while(~scanf("%d %d", &l, &r))
{
Prime(l, r);
}
return 0;
}