1. 程式人生 > >UVA10140 Prime Distance

UVA10140 Prime Distance

bottom style print 質數 prime 刪除 cal 我們 there

題意翻譯

大致意思:給定兩個整數L,R(1<=L<=R<=2147483648,R-L<=1000000),求閉區間 [L,R]中相鄰兩個質數的差的最小值和最大值是多少,分別輸出這兩個質數。

【輸入格式】

輸入有若幹行,每行兩個整數 L,R

【輸出格式】

對於每個L,R輸出最小值和最大值,格式參照樣例。若區間內無質數,輸出"There are no adjacent primes."。

分割線

看到這題,瞄一眼數據範圍,噫,2的31次方,比int範圍大了1,然後看到了下一句,咦?R-L好小,只有一百萬,所以,我們從這方面入手。

首先,先把2到根號R中的質數篩出來,根號R很小,不超過五萬,此為預處理,L到R中的質數其實只要

到根號R,因為大於根號R的質數要麽是一個小質數乘一個大質數,而先前因為小質數已經將這種的篩掉了,要麽是大質數乘大質數,已經超過了R,不在處理範圍,然而小質數乘小質數也不超過根號R(此處小質數指小於根號R的質數,大質數指大於根號R的質數)。

然後我註意到了是多組數據,所以開頭的一堆附初值是少不了的,切記不要忘掉!

之後,枚舉一個質數,找到它的第一個倍數(在L到R區間內),和最後一個倍數,在此區間內枚舉,刪掉質數的倍數,再掃一遍得到一個質數表。

最後,就是相鄰質數之差選一個最小和最大,這好辦,枚舉一個i,和i+1做差即可。

數學題哭唧唧qwq

代碼如下:(註意開longlong,有乘法的時候要乘1ll,把它暫時變為longlong類型其實全開longlong了乘不乘也沒什麽關系>_>


#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<iostream>
#include<algorithm>
#define ll long long
#define M 1000010
using namespace std;
ll l,r,flag,cnt,cnt1,cnt2,ans1,ans2,ans3,ans4,vis[M],a[M],b[M],c[M],c2[M],c3[M],minn,maxx;
int main() { for(ll i=2;i<=50000;i++) { if(vis[i]==0) { a[++cnt]=i; for(ll j=i+i;j<=50000;j+=i) { vis[j]=1; } } } while(scanf("%lld%lld",&l,&r)!=EOF) { flag=0; memset(vis,0,sizeof(vis)); for(ll i=1;i<=cnt;i++) { for(ll j=l/a[i];j<=r/a[i];j++)//得到l到r區間的a[i]的倍數 { if(1ll*a[i]*j-l<0)continue; if(j>1)vis[1ll*a[i]*j-l]=1;//我們不能刪除這個質數本身,也就是1倍的a[i],大於等於2以上的倍數才能刪掉,這裏特判 } } cnt1=cnt2=0; if(l==1)vis[0]=1; for(ll i=l;i<=r;i++) { if(vis[i-l]==0)b[++cnt1]=i,flag++; } if(flag<=1){printf("There are no adjacent primes.\n");} else if(flag>1) { for(ll i=1;i<=cnt1-1;i++) { c[++cnt2]=b[i+1]-b[i]; c2[cnt2]=b[i]; c3[cnt2]=b[i+1]; } minn=1e18; maxx=0; for(ll i=1;i<=cnt2;i++) { if(minn>c[i]){minn=c[i];ans1=c2[i];ans2=c3[i];} if(maxx<c[i]){maxx=c[i];ans3=c2[i];ans4=c3[i];} } printf("%lld,%lld are closest, %lld,%lld are most distant.\n",ans1,ans2,ans3,ans4); } } return 0; }

end.謝謝閱讀

UVA10140 Prime Distance