poj2689 Prime Distance(思维+筛素数)
Prime Distance
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
Sample Input
2 17
14 17
Sample Output
2,3 are closest, 7,11 are most distant. There are no adjacent primes.
题意:给你一个区间[L,R],求闭区间 [L,R]中相邻两个质数差值最小的数对与差值最大的数对。当存在多个时,输出靠前的素数对。
思路:直接暴力找的话,肯定会超时。既然是和素数相关数据又大,肯定就要先打一个素数表了,但是L,R是<=109的,如果素数表是从1到109筛选的话,还是会超时,于是我们只能筛选两次,打完素数表之后,再从L,R筛选素数,和打表的思路一样,都是标记非素数,再找出素数,然后比较相邻的差并且记录即可。
代码如下:(索性直接全部long long)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<vector> 5 using namespace std; 6 typedef long long ll; 7 const ll maxn=1e6+5; 8 const ll inf=0x3f3f3f3f; 9 bool isprime[maxn]; 10 bool isprimelr[maxn]; 11 ll prime[maxn]; 12 void makeprime()//筛素数得到素数表 13 { 14 ll cnt=0; 15 memset(isprime,true,sizeof(isprime)); 16 for(ll i=2;i<=maxn;i++) 17 { 18 if(isprime[i]) 19 prime[++cnt]=i; 20 for(ll j=1;j<=cnt;j++) 21 { 22 if(i*prime[j]>maxn) 23 break; 24 isprime[i*prime[j]]=false; 25 if(i%prime[j]==0) 26 break; 27 } 28 } 29 return ; 30 } 31 ll cnt=0; 32 vector<ll> v; 33 void makeprimelr(ll l,ll r)//再筛一次,得到[l,r]之间的素数表 v(vector类型的) 34 { 35 if(l==1)//1不算,从2开始 36 l++; 37 memset(isprimelr,true,sizeof(isprimelr)); 38 for(ll i=1;prime[i]*prime[i]<=r;i++) 39 { 40 ll k=l/prime[i]; 41 if(k<=1)//从这个质数的第一个倍数开始标记,比如质数是3,第一个倍数就是6 42 k=2; 43 for(ll j=k*prime[i];j<=r;j+=prime[i]) 44 { 45 isprimelr[j-l]=false;//标记不是素数的,和上边第一个筛素数的函数思路一样,并进行压缩 46 } 47 } 48 for(ll i=0;i<=r-l;i++)//把是素数的放入v 49 { 50 if(isprimelr[i]) 51 v.push_back(i+l);//还原 52 } 53 return ; 54 } 55 ll minl,minr,mind; 56 ll maxl,maxr,maxd; 57 bool work() 58 { 59 if(v.size()<=1) 60 return false; 61 for(ll i=1;i<v.size();i++) 62 { 63 if(v[i]-v[i-1]<mind) 64 { 65 mind=v[i]-v[i-1]; 66 minl=v[i-1]; 67 minr=v[i]; 68 } 69 if(v[i]-v[i-1]>maxd) 70 { 71 maxd=v[i]-v[i-1]; 72 maxl=v[i-1]; 73 maxr=v[i]; 74 } 75 } 76 return true; 77 } 78 int main() 79 { 80 ll l,r; 81 while(~scanf("%lld%lld",&l,&r)) 82 { 83 v.clear(); 84 makeprime(); 85 makeprimelr(l,r); 86 mind=inf; 87 maxd=0; 88 if(work()) 89 printf("%lld,%lld are closest, %lld,%lld are most distant.\n",minl,minr,maxl,maxr); 90 else 91 printf("There are no adjacent primes.\n"); 92 } 93 return 0; 94 }