本题的大意是,每次给定两个int范围内的数l,r,其中r-l <= 1000000,求出[l,r]之内的所有素数距离最近的一对和距离最远的一对。
这个题直接暴力枚举肯定T,于是之后我还有一种沙雕办法,就是先筛出来1~√r之内所有的素数,这样的话就可以来筛区间内的素数了……于是我就又每一个跑了一遍根号算法(我本来以为只枚举素数不会T的)
还是非常稳妥的T了。
于是乎采取一种新的办法,我们预处理出来素数之后,我们可以只枚举在这个区间范围内的数,我们用每个素数去筛掉他们就行了,这样的话就不会T了……
看一下代码。
#include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #include<cmath> #include<set> #include<vector> #include<queue> #define pb push_back #define rep(i,a,n) for(int i = a;i <= n;i++) #define per(i,n,a) for(int i = n;i >= a;i--) #define enter putchar(' ') using namespace std; typedef long long ll; const int M = 40005; const int N = 1000005; const int INF = 1000000009; const ll mod = 51123987; ll read() { ll ans = 0,op = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') op = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { ans *= 10; ans += ch - '0'; ch = getchar(); } return ans * op; } int l,r,pri[N],dpri[N],tot1,tot2,maxn,minn,mip1,mip2,map1,map2; bool np[N],vis[N]; void euler() { int n = 50000; np[1] = 1; rep(i,2,n) { if(!np[i]) pri[++tot1] = i; for(int j = 1;i * pri[j] <= n;j++) { np[i * pri[j]] = 1; if(!(i%pri[j])) break; } } } int main() { euler(); while(scanf("%d %d",&l,&r) != EOF) { maxn = 0,minn = INF; if(l == 1) vis[0] = 1; rep(i,1,tot1) { int g = l / pri[i]; if(l % pri[i]) g++; for(int j = g;j <= r / pri[i];j++) if(j != 1) vis[pri[i] * j - l] = 1; } //rep(i,0,r-l) printf("%d ",vis[i]);enter; rep(i,0,r-l) { if(!vis[i]) dpri[++tot2] = i+l; if(tot2 <= 1) continue; if(dpri[tot2] - dpri[tot2-1] > maxn) maxn = dpri[tot2] - dpri[tot2-1],map1 = dpri[tot2 - 1],map2 = dpri[tot2]; if(dpri[tot2] - dpri[tot2-1] < minn) minn = dpri[tot2] - dpri[tot2-1],mip1 = dpri[tot2 - 1],mip2 = dpri[tot2]; } if(tot2 <= 1) printf("There are no adjacent primes. "); else printf("%d,%d are closest, %d,%d are most distant. ",mip1,mip2,map1,map2); rep(i,0,r-l) vis[i] = 0;tot2 = 0; } return 0; }