因为最大可以达到int极限
明显直接筛选不可能完成
所以从其因子入手
因为任何不是素数的数都有除了1与其自身之外的因子
因此,我们筛出2^(31/2)≈46350之内的所有素数,以其作为因子再将题目给定区间内的所有不是素数的数标记排除
然后将素数存放在prnum这个vector集合中便于调用
在排除阶段,可以用
l=((L+prnum[i]-1)/prnum[i])*prnum[i]
计算出区间内的第一个是prnum[i]的倍数的数
注意,如果计算出来的使其本身,取倍数
再用
r=R/prnum[i]*prnum[i]
计算出最后一个是prnum[i]的倍数的数
符合条件时,从l到r,每次加prnum[i],标记出所有以prnum[i]为因子的数
因为无法直接开数组标记到大数
但又因为R-L≤1000000
所以可以对位置进行转换
标记时取-L+1,取出时取-1+L
最后将区间内的素数取出放在ans这个vector集合内,对答案进行判断即可
(注意特殊情况的判断)
1 /* 2 Written By StelaYuri 3 */ 4 #include<bits/stdc++.h> 5 using namespace std; 6 typedef long long ll; 7 vector<ll> prnum,ans; 8 bool prim[46400],ar[1000010]; 9 int main(){ 10 ll L,R,i,j,cnt,l,r,mxdis,mndis,mxn1,mxn2,mnn1,mnn2,d; 11 scanf("%lld%lld",&L,&R); 12 memset(prim,true,sizeof prim); 13 prim[0]=prim[1]=false; 14 for(i=2;i<=215;i++) 15 if(prim[i]) 16 for(j=2*i;j<=46350;j+=i) 17 prim[j]=false;//埃氏筛法 18 prnum.push_back(2); 19 for(i=3;i<=46349;i+=2) 20 if(prim[i]) 21 prnum.push_back(i);//将素数放置在prnum内 22 cnt=prnum.size(); 23 memset(ar,true,sizeof ar); 24 if(L==1) 25 ar[1]=false; 26 for(i=0;i<cnt;i++){ 27 l=((L+prnum[i]-1)/prnum[i])*prnum[i]; 28 if(l==prnum[i])//如果计算得出的l恰好为第i个素数本身,跳过它,取其倍数 29 l+=l; 30 if(l>R) 31 continue; 32 r=R/prnum[i]*prnum[i]; 33 for(j=l;j<=r;j+=prnum[i]) 34 ar[j-L+1]=false;//标记 35 } 36 for(i=1;i<=R-L+1;i++) 37 if(ar[i]) 38 ans.push_back(i-1+L);//将指定区间内的所有素数提出 39 cnt=ans.size(); 40 if(cnt<2) 41 puts("There are no adjacent primes."); 42 else{ 43 mndis=mxdis=ans[1]-ans[0]; 44 mxn1=mnn1=ans[0]; 45 mxn2=mnn2=ans[1]; 46 for(i=2;i<cnt;i++){ 47 d=ans[i]-ans[i-1]; 48 if(d>mxdis){ 49 mxdis=d; 50 mxn1=ans[i-1]; 51 mxn2=ans[i]; 52 } 53 if(d<mndis){ 54 mndis=d; 55 mnn1=ans[i-1]; 56 mnn2=ans[i]; 57 } 58 } 59 printf("%lld,%lld are closest, %lld,%lld are most distant.\n",mnn1,mnn2,mxn1,mxn2); 60 } 61 62 return 0; 63 }
来源:https://www.cnblogs.com/stelayuri/p/12233657.html