Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 12811 | Accepted: 3420 |
Description
Input
Output
Sample Input
2 17 14 17
Sample Output
2,3 are closest, 7,11 are most distant. There are no adjacent primes.
Source
给出一个区间[L,R], 范围为1<=L< R<=2147483647,区间长度长度不超过1000000
求距离最近和最远的两个素数(也就是相邻的差最小和最大的素数)
筛两次,第一次筛出1到1000000的素数,因为1000000^2已经超出int范围,这样的素数足够了。
函数getPrim(); prime[ ] 存第一次筛出的素数,总个数为prime[0]
第二次利用已经筛出的素数去筛L,R之间的素数
函数getPrime2(); isprime[] 判断该数是否为素数 prime2[ ]筛出的素数有哪些,一共有prime2[0]个
代码:
#include <iostream> #include <string.h> #include <stdio.h> #include <cmath> #include <algorithm> using namespace std; const int maxn=1e6; int prime[maxn+10]; void getPrime() { memset(prime,0,sizeof(prime));//一开始prime都设为0代表都是素数(反向思考) for(int i=2;i<=maxn;i++) { if(!prime[i]) prime[++prime[0]]=i; for(int j=1;j<=prime[0]&&prime[j]<=maxn/i;j++) { prime[prime[j]*i]=1;//prime[k]=1;k不是素数 if(i%prime[j]==0) break; } } } bool isprime[maxn+10]; int prime2[maxn+10]; void getPrime2(int L,int R) { memset(isprime,1,sizeof(isprime)); //isprime[0]=isprime[1]=0;//这句话不能加,考虑到左区间为2的时候,加上这一句,素数2,3会被判成合数 if(L<2) L=2; for(int i=1;i<=prime[0]&&(long long)prime[i]*prime[i]<=R;i++) { int s=L/prime[i]+(L%prime[i]>0);//计算第一个比L大且能被prime[i]整除的数是prime[i]的几倍,从此处开始筛 if(s==1)//很特殊,如果从1开始筛的话,那么2会被筛成非素数 s=2; for(int j=s;(long long)j*prime[i]<=R;j++) if((long long)j*prime[i]>=L) isprime[j*prime[i]-L]=false; //区间映射 ,比如区间长度为4的区间[4,7],映射到[0,3]中,因为题目范围2,147,483,647数组开不出来 } prime2[0]=0; for(int i=0;i<=R-L;i++) if(isprime[i]) prime2[++prime2[0]]=i+L; } int main() { getPrime(); int L,R; while(scanf("%d%d",&L,&R)!=EOF) { getPrime2(L,R); if(prime2[0]<2) printf("There are no adjacent primes.\n"); else { int x1=0,x2=1000000,y1=0,y2=0; for(int i=1;i<prime2[0];i++) { if(prime2[i+1]-prime2[i]<x2-x1) { x1=prime2[i]; x2=prime2[i+1]; } if(prime2[i+1]-prime2[i]>y2-y1) { y1=prime2[i]; y2=prime2[i+1]; } } printf("%d,%d are closest, %d,%d are most distant.\n",x1,x2,y1,y2); } } return 0; }