POJ-2689 Prime Distance (两重筛素数,区间平移)

Prime Distance

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 13961   Accepted: 3725

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.

题目大意:给一个区间,找出这个区间内相邻的两个素数中差最大和最小的两个。题目解析:两种方法,一种是 枚举 + Miller_Rabbin快速判定素数,另一种是将标记数组区间平移,两次筛素数。

第一种方法:

 1 # include<iostream>
 2 # include<cstdio>
 3 # include<cstring>
 4 # include<cstdlib>
 5 # include<algorithm>
 6 using namespace std;
 7 # define ll long long
 8 unsigned mypow(unsigned a,unsigned b,unsigned m)
 9 {
10     if(b==0)
11         return 1;
12     if(b==1)
13         return a%m;
14     ll temp=mypow(a,b/2,m);
15     temp*=temp;
16     temp%=m;
17     if(b&1)
18         temp*=a;
19     temp%=m;
20     return temp;
21 }
22 bool Miller_Rabbin(unsigned x)
23 {
24     if(x==2)
25         return true;
26     for(int i=1;i<=2;++i){
27         unsigned a=rand()%(x-2)+2;
28         if(mypow(a,x-1,x)!=1)
29             return false;
30     }
31     return true;
32 }
33 int main()
34 {
35     unsigned a,b;
36     unsigned l1,l2,r1,r2,t;
37     int minn,maxn;
38     while(scanf("%u%u",&a,&b)!=EOF)
39     {
40         if(a==1)
41             a=2;
42         minn=1000005;
43         maxn=0;
44         l1=l2=r1=r2=a;
45         bool yy=true;
46         for(int i=a;i<=b;++i){
47             if(Miller_Rabbin(i)){
48                 if(yy){
49                     t=l1=r1=a;
50                     yy=false;
51                 }
52                 else{
53                     if(minn>i-t){
54                         minn=i-t;
55                         l1=t;
56                         l2=i;
57                     }
58                     if(maxn<i-t){
59                         maxn=i-t;
60                         r1=t;
61                         r2=i;
62                     }
63                 }
64                 t=i;
65             }
66         }
67         if(maxn==0){
68             printf("There are no adjacent primes.\n");
69         }else
70             printf("%u,%u are closest, %u,%u are most distant.\n",l1,l2,r1,r2);
71     }
72     return 0;
73 }

这种暴力的方法效率不高,在UVa上取30个随机数能AC,在ZOJ上取20个随机数能AC,但在POJ上无论如何都AC不了。原因就是这三个OJ对时间的要求分别是3s,2s,1s。

下面是两重筛的实现。标记数组用的很灵活。

 1 # include<iostream>
 2 # include<cstdio>
 3 # include<cmath>
 4 # include<map>
 5 # include<vector>
 6 # include<cstring>
 7 # include<algorithm>
 8 using namespace std;
 9 const int N=46340;
10 int pri[N],mark[1000010],cnt;
11 vector<unsigned>v;
12 void init()
13 {
14     cnt=0;
15     fill(mark,mark+N+5,1);
16     for(int i=2;i<=N;++i){
17         if(mark[i])
18             pri[cnt++]=i;
19         for(int j=0;j<cnt&&i*pri[j]<=N;++j){
20             mark[i*pri[j]]=0;
21             if(i%pri[j]==0)
22                 break;
23         }
24     }
25 }
26 void work(unsigned a,unsigned b)
27 {
28     v.clear();
29     if(a==1)
30         ++a;
31     memset(mark,0,sizeof(mark));
32     for(int i=0;i<cnt;++i){
33         if(pri[i]>b)
34             break;
35         for(int c=a/pri[i];c*pri[i]<=b;++c){
36             if(c<=1)
37                 continue;
38             if(c*pri[i]<a)
39                 continue;
40             mark[c*pri[i]-a]=1;
41         }
42     }
43     for(int i=0;i<=b-a;++i){
44         if(mark[i]==0)
45             v.push_back(i+a);
46     }
47 }
48 void solve()
49 {
50     int l=v.size();
51     if(l<2){
52         printf("There are no adjacent primes.\n");
53         return ;
54     }
55     int minn=1<<30,maxn=0;
56     unsigned l1,l2,r1,r2;
57     for(int i=1;i<l;++i){
58         if(minn>v[i]-v[i-1]){
59             minn=v[i]-v[i-1];
60             l1=v[i-1];
61             l2=v[i];
62         }
63         if(maxn<v[i]-v[i-1]){
64             maxn=v[i]-v[i-1];
65             r1=v[i-1];
66             r2=v[i];
67         }
68     }
69     printf("%u,%u are closest, %u,%u are most distant.\n",l1,l2,r1,r2);
70 }
71 int main()
72 {
73     init();
74     unsigned a,b;
75     while(scanf("%u%u",&a,&b)!=EOF)
76     {
77         work(a,b);
78         solve();
79     }
80     return 0;
81 }

时间: 2024-11-05 13:28:57

POJ-2689 Prime Distance (两重筛素数,区间平移)的相关文章

[ACM] POJ 2689 Prime Distance (筛选范围大素数)

Prime Distance Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 12811   Accepted: 3420 Description The branch of mathematics called number theory is about properties of numbers. One of the areas that has captured the interest of number th

poj 2689 Prime Distance 【数论】【筛法求素数】

题目链接:传送门 题目大意: 给你L和R两组数,L和R的范围是2^32,其间隔(即R-L最大为1,000,000.) .让你求出L和R之间素数的最大间隔和最小的间隔. 比如 2 17.之间的最小素数间隔是2 3,最大的素数间隔是11 17. 要是直接进行一个2^32次方筛法然后在判断是会T的. 我们这样来想,筛法求素数的原理是什么: /**vis数组标记为0则说明是素数*/ int vis[10005]; void getPrimevis(int n) { int m=sqrt(n+0.5);

POJ 2689 Prime Distance 素数筛选法应用

题目来源:POJ 2689 Prime Distance 题意:给出一个区间L R 区间内的距离最远和最近的2个素数 并且是相邻的 R-L <= 1000000 但是L和R会很大 思路:一般素数筛选法是拿一个素数 然后它的2倍3倍4倍...都不是 然后这题可以直接从2的L/2倍开始它的L/2+1倍L/2+2倍...都不是素数 首先筛选出一些素数 然后在以这些素数为基础 在L-R上在筛一次因为 R-L <= 1000000 可以左移开一个1百万的数组 #include <cstdio>

poj 2689 Prime Distance(大区间筛素数)

http://poj.org/problem?id=2689 题意:给出一个大区间[L,U],分别求出该区间内连续的相差最小和相差最大的素数对. 因为L<U<=2147483647,直接筛素数是不行的,数组就开不了.但是可以根据素数筛的原理.我们先筛出sqrt(2147483647)以内的素数,然后拿这些素数去筛[L,U]之间的素数,即两次素数筛.但是L,U还是很大,但U-L<=1000000,所以进行区间平移,将[L,U]平移为[0,U-L],就能用数组放得下. #include &l

数论 - 素数的运用 --- poj 2689 : Prime Distance

Prime Distance Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 12512   Accepted: 3340 Description The branch of mathematics called number theory is about properties of numbers. One of the areas that has captured the interest of number th

[ACM] POJ 2689 Prime Distance (大区间素数筛选)

Prime Distance Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 12811   Accepted: 3420 Description The branch of mathematics called number theory is about properties of numbers. One of the areas that has captured the interest of number th

POJ 2689 Prime Distance(素数区间筛法--经典题)

大致题意:给定[L,R]区间,找出区间内的每个素数 数据范围 : 1<=L< R<=2,147,483,647) R-L <=1,000,000. R的数值太大,所以不能直接筛[0,R]的,要空间和时间优化,用到区间筛法,另外注意不能用int,因为R和L都是满int的,中间有很多细节处理会爆int的,还要注意1不是素数,所以在区间筛中要特判一下,是个易错的地方 //1160K 16MS C++ 1539B #include<cstdio> #include<ios

POJ 2689 Prime Distance

Prime Distance 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

poj 2689 Prime Distance(筛一个区间内的素数(或合数))

: [题意说明] 给你指定的范围[L, U],在这个范围内找出相邻最近和最远的两组质数,若最近或最远值相同,输出较小的那组.其中:1≤L,另U-L≤1000000. [问题分析] 此题与质数有关,显然若是能求出[L, U]之间的质数,然后从前往后扫描一遍即可出需要的结果,但问题是L与U的范围太大,是不可能在规定的时间内实现的. 但这里给我们提供了另一个条件:U-L≤1000000,如果我们只求1000000以内的素数,完全可以在规定的时间实现的!但由于所求的不是1-1000000以内的素数,所以