题意翻译
大致意思:给定两个整数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. ");} 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. ",ans1,ans2,ans3,ans4); } } return 0; }
end.谢谢阅读