Description
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
Output
Sample Input
2 17 14 17
Sample Output
2,3 are closest, 7,11 are most distant. There are no adjacent primes.
解題思路
找出給出的範圍內,相鄰最近和最遠的兩個素數,用到了篩素數法,因爲 1 <= L < U <= 2,147,483,647 所以只要先找出50000以內的素數,再對給出的範圍再次篩選就行了。
因爲範圍的數值較大,所以數組記錄素數時要用到映射。
AC代碼
#include <cstdio>
#include <cstring>
#define maxn 1000001
#define LL long long
LL p_list[50000], p_cnt; //p_list[]存儲50000範圍內的素數,p_cnt計數
LL map[maxn], p_map[maxn], count; //map[]存儲給定範圍內素數的情況p_map[],count計數
void get_prime()
{
LL p_tmp[50000];
memset(p_tmp, 0, sizeof(p_tmp));
for(int i = 2; i < 50000; i++)
{
if( p_tmp[i] == 0 )
{
p_list[p_cnt++] = i;
for(int k = i * 2; k < 50000; k += i)
p_tmp[k] = 1;
}
}
}
int main()
{
LL a, b;
get_prime();
while(scanf("%lld%lld", &a, &b) != EOF)
{
if(a == 1)
a++;
memset(map, 0, sizeof(map));
for(LL i = 0; i < p_cnt && p_list[i] * p_list[i] <= b; i++) //篩選[a, b]內的素數,map[]記錄篩選結果
{
LL tmp = a / p_list[i];
if(tmp * p_list[i] != a)
tmp++;
if(tmp == 1)
tmp++;
for(LL j = tmp * p_list[i]; j <= b; j += p_list[i])
map[j - a] = 1; //映射
}
count = 0;
for(LL i = a; i <= b; i++) //p_map[]記錄篩選出來的素數
if(map[i - a] == 0)
p_map[count++] = i;
if(count < 2)
printf("There are no adjacent primes.\n");
else
{
LL m1 = p_map[0], m2 = p_map[1], n1 = p_map[0], n2 = p_map[1]; //找出相鄰最近和最遠的兩個素數
for(int i = 2; i < count; i++)
{
if(p_map[i] - p_map[i - 1] < m2 - m1)
m2 = p_map[i], m1 = p_map[i - 1];
if(p_map[i] - p_map[i - 1] > n2 - n1)
n2 = p_map[i], n1 = p_map[i - 1];
}
printf("%lld,%lld are closest, %lld,%lld are most distant.\n", m1, m2, n1, n2);
}
}
return 0;
}
<pre name="code" class="csharp">