题目:
给出一个区间[L,R]求在该区间内的素数最短,最长距离。 (R < 2 * 10^9 , R - L <= 10 ^ 6)
由数论知识可得一个数的因子可在开根号内得到。所以,我们可以打出5*10^4内得素数。然后,在用一次筛法把在[L,R]内得合数找到,则剩下的就是素数了。这里要用到离散化,把一个数 x - L 保存在数组里。因为,直接保存肯定不行,但是我们发现区间特点较小。所以,可以想到离散化。
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <cmath> using namespace std; typedef long long LL; const int MAXN = 50000; int primes[MAXN]; bool vst[MAXN]; int notPrimes[1000010]; int pos[1000010]; int top,pcnt; void init(){ top = 0; memset(vst,0,sizeof(vst)); vst[0] = vst[1] = 1; for(int i = 2;i < MAXN;++i)if(!vst[i]){ primes[top++] = i; for(int j = i + i;j < MAXN;j += i) vst[j] = 1; } //printf("top: %d\n",top); } void solve(int L,int R){ memset(notPrimes,0,sizeof(notPrimes)); if(L == 1) L = 2; /// 防止筛掉所有该区间的素数本身!!!!! for(int i = 0;i < top&&(LL)primes[i]*primes[i] <= R;++i){ //筛选因子 int s = L / primes[i] + (L % primes[i] > 0); //当前素数的最小倍数达到L s = (s == 1 ? 2 : s); /// 防止筛掉所有该区间的素数本身!!!!! for(int j = s;(LL)j*primes[i] <= R;++j){ if((LL)j*primes[i] >= L) //合数 notPrimes[j*primes[i] - L] = 1; // 相当与离散化 } } pcnt = 0; for(int i = 0;i <= R - L;++i){ if(!notPrimes[i]){ pos[pcnt++] = i + L; //printf("i -- > %d\n",i + L); } } if(pcnt < 2){ puts("There are no adjacent primes."); } else { int minl,minr,maxl,maxr,minv = 999999,maxv = -1; for(int i = 1;i < pcnt;++i){ if(pos[i] - pos[i-1] > maxv){ maxv = pos[i] - pos[i-1]; maxl = pos[i-1]; maxr = pos[i]; } if(pos[i] - pos[i-1] < minv){ minv = pos[i] - pos[i-1]; minl = pos[i-1]; minr = pos[i]; } } printf("%d,%d are closest, %d,%d are most distant.\n",minl,minr,maxl,maxr); } } int main() { init(); int L,R; while(~scanf("%d%d",&L,&R)){ solve(L,R); } return 0; }
时间: 2024-10-22 09:32:33