1. 程式人生 > >POJ 2689 - Prime Distance - [篩法求素數]

POJ 2689 - Prime Distance - [篩法求素數]

代碼 one mini rop esc imu script less ogr

題目鏈接:http://poj.org/problem?id=2689

Time Limit: 1000MS Memory Limit: 65536K

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.

題意:

給出st與ed(1 <= st < ed <= 2147483647 且 ed - st <= 1000000),求[st,ed]區間內,相鄰的兩個素數中,差最小的和差最大的(若存在差同樣大的一對素數,則有先給出最小的一對素數);

題解:

顯然,不可能直接去篩2147483647以內的素數;

不難觀察到,ed - st <= 1000000,可以直接去篩每個test case的[st,ed]區間內的素數;

那麽,我們不妨先用歐拉篩法篩出[0,46341]區間內的素數(46341≈sqrt(2147483647));

然後對於每個test case的[st,ed]區間,我們采用埃篩的方法,用已經篩選出的在[0,46341]區間內的素數,去篩[st,ed]區間內的素數;

AC代碼:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cmath>
 4 #define MAX 46345
 5 typedef long long ll;
 6 
 7 bool isPrime[1000005];
 8 
 9 //歐拉篩法求[0,46345]內的素數 - begin
10 int Prime1[MAX],cnt1;
11 void screen1()
12 {
13     memset(isPrime,1,sizeof(isPrime));
14     cnt1=0;
15     isPrime[0]=isPrime[1]=0;
16     for(int i=2;i<=MAX;i++)
17     {
18         if(isPrime[i]) Prime1[cnt1++]=i;
19         for(int j=0;j<cnt1;j++)
20         {
21             if(i*Prime1[j]>MAX) break;
22             isPrime[(i*Prime1[j])]=0;
23             if(i%Prime1[j]==0) break;
24         }
25     }
26 }
27 //歐拉篩法求[0,46345]內的素數 - end
28 
29 //埃篩求[st,ed]內的素數 - begin
30 ll st,ed;
31 ll Prime2[1000005];
32 int cnt2;
33 void screen2()
34 {
35     memset(isPrime,1,sizeof(isPrime));
36     for(int i=0;i<cnt1;i++)
37     {
38         if(Prime1[i]>ed) break;//這種情況下,已經不可能再篩了,跳出
39 
40         ll tmp=st/Prime1[i];
41         while(tmp*Prime1[i]<st) tmp++;
42         while(tmp<=1) tmp++;
43         
44         for(ll j=tmp*Prime1[i];j<=ed;j+=Prime1[i]) isPrime[j-st]=0;
45     }
46     if(st==1) isPrime[0]=0;
47         //得到了[st,ed]內的素數的標記數組
48         
49     cnt2=0;
50     for(ll i=st;i<=ed;i++)
51     {
52         if(isPrime[i-st]) Prime2[cnt2++]=i;
53     }
54         //根據標記數組,得到存儲[st,ed]內所有素數的數組
55 }
56 //埃篩求[st,ed]內的素數 - end
57 
58 int main()
59 {
60     screen1();
61     while(scanf("%lld%lld",&st,&ed)!=EOF)
62     {
63         screen2();
64         if(cnt2<=1)
65         {
66             printf("There are no adjacent primes.\n");
67             continue;
68         }
69         else
70         {
71             ll min_dist=0x3f3f3f3f,max_dist=0;
72             ll c1,c2,d1,d2;
73             for(int i=0;i<cnt2-1;i++)
74             {
75                 if(Prime2[i+1]-Prime2[i]<min_dist)
76                 {
77                     min_dist=Prime2[i+1]-Prime2[i];
78                     c1=Prime2[i], c2=Prime2[i+1];
79                 }
80                 if(Prime2[i+1]-Prime2[i]>max_dist)
81                 {
82                     max_dist=Prime2[i+1]-Prime2[i];
83                     d1=Prime2[i], d2=Prime2[i+1];
84                 }
85             }
86             printf("%I64d,%I64d are closest, %I64d,%I64d are most distant.\n",c1,c2,d1,d2);
87         }
88     }
89 }

POJ 2689 - Prime Distance - [篩法求素數]