POJ2689 Prime Distance [区间筛]
分析
数据范围很大——开数组存储所有素数状态会爆;但是区间较小,所以是区间筛。先将 \(\sqrt{2,147,483,647}\approx46341\) 以下的素数全部筛出,并存储起来。对于每次查询,将每个质数p,标记\(i*p , (\lceil \frac{L}{p} \rceil \leq i \leq \lfloor \frac {R}{P}\rfloor )\)。其余根据题意模拟即可。
曾出现的错误
- 特判:当 \(l==1\) 时,要将 \(l\) 所在的位置标 \(1\) 。
- 每次比较成功之后,要将极值更新为当前值。
- 不开
long long
见祖宗。 这题我调了将近一个星期。
code
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
bool np[47000];
ll pr[5000];
bool v[1000000 + 5];
int Er(int n)
{
int m = floor(sqrt(n));
np[1] = np[0] = 1;
for (int i = 2; i <= m; i++)
{
if (!np[i])
{
for (int j = i * i; j <= n; j += i)
np[j] = 1;
}
}
int cnt = 0;
for (int i = 2; i <= 46999; i++)
{
if (!np[i])
pr[++cnt] = i; //[1,cnt];
}
return cnt;
}
void test(ll n[],int cnt){
for(int i=1;i<=cnt;i++)
printf("%ld\t",n[i]);
}
int main()
{
int cnt = Er(47000);
// test( pr , cnt);
//预处理完毕 ,素数装载完成 : [1 , cnt];
long long l, r;
while (scanf("%ld%ld", &l, &r) != EOF)
{
for(int i=0;i<=100000;i++){
v[i]=0;
}
//上面慎用 memset , 会出现错误 , 原因尚不清楚
if (l == 1)
v[0] = 1;//1 要特判
//================核 心 —— 区 间 筛=================
for (ll i = 1; i <= cnt && pr[i] <= r; i++)
{
for (ll j = (l - 1) / pr[i] + 1; j <= r / pr[i]; j++)
{
if (j > 1)
v[j * pr[i] - l] = 1;
}
}
//筛选完毕 进行模拟
bool fst = 1;
int posl = 0, posr = 0; //左、右指针的位置
int dst = 0; //distance
int c1 = 0, c2 = 0, dst_c = 1e9; //closest 1,2:差值最小的两个指针;最大的差值 max difference
int d1 = 0, d2 = 0, dst_d = -1; //most distant 1,2:差值最大的两个相邻指针; 差值
for (int i = l - l; i <= r - l; i++)
{
if (!v[i])
{ //i号是质数
if (fst)//如果是第一次找到素数
posl = i;
dst = i - posr;//与上一个素数的间距
if (!fst && dst < dst_c)
{ //不是第一个素数 && 差值比之前大
// printf("\n最小差值changed:i=%d posr=%d\n",i,posr);
c1 = posr;
c2 = i;
dst_c = dst;
}
if (!fst && dst > dst_d)
{ //不是第一个素数 && 差值比之前大
// printf("\n最大差值changed:i=%d posr=%d\n",i,posr);
d1 = posr;
d2 = i;
dst_d = dst;
}
posr = i;
fst = 0;
}
}
if (posl == posr)
{
printf("There are no adjacent primes.\n");
}
else
{
printf("%d,%d are closest, %d,%d are most distant.\n",
c1 + l, c2 + l, d1 + l, d2 + l);
}
}
return 0;
}
题目
Prime Distance
Time Limit: 1000MS | Memory Limit: 65536K | |
---|---|---|
Total Submissions: 30893 | Accepted: 7897 |
Description
The branch of mathematics called number theory is about properties of numbers. One of the areas that has captured the interest of number theoreticians for thousands of years is the question of primality. A prime number is a number that is has no proper factors (it is only evenly divisible by 1 and itself). The first prime numbers are 2,3,5,7 but they quickly become less frequent. One of the interesting questions is how dense they are in various ranges. Adjacent primes are two numbers that are both primes, but there are no other prime numbers between the adjacent primes. For example, 2,3 are the only adjacent primes that are also adjacent numbers.
Your program is given 2 numbers: L and U (1<=L< U<=2,147,483,647), and you are to find the two adjacent primes C1 and C2 (L<=C1< C2<=U) that are closest (i.e. C2-C1 is the minimum). If there are other pairs that are the same distance apart, use the first pair. You are also to find the two adjacent primes D1 and D2 (L<=D1< D2<=U) where D1 and D2 are as distant from each other as possible (again choosing the first pair if there is a tie).
Input
Each line of input will contain two positive integers, L and U, with L < U. The difference between L and U will not exceed 1,000,000.
Output
For each L and U, the output will either be the statement that there are no adjacent primes (because there are less than two primes between the two given numbers) or a line giving the two pairs of adjacent primes.
Sample Input
2 17
14 17
Sample Output
2,3 are closest, 7,11 are most distant.
There are no adjacent primes.