质数距离
输入样例:
2 17
14 17
输出样例:
2,3 are closest, 7,11 are most distant.
There are no adjacent primes.
解题思路:
我们无法预处理 1 < n < 2 31 − 1 1 \lt n \lt 2^{31} - 1 1<n<231−1 的所有质数。对于一个数 n , 最多存在一个大于 x \sqrt x x 的质因数。所以我们可以预先处理不超过 x \sqrt x x 的质数,然后筛除 [L,U] 之间的合数。
2 31 ≈ 46340 \sqrt {2^{31}} \approx 46340 231≈46340 是可以用线性筛法筛出的
预处理完primes数组后 , 我们用primes数组中的素数筛掉 [L,U] 之间的合数, 对于每一个素数primes[i] , 最先筛掉的应该是 L / p r i m e s [ i ] L / primes[i] L/primes[i] 倍的 primes[i] , 当然 要注意到两种特殊情况
- primes[i] == L
- primes[i] > L
令 j = L / p r i m e s [ i ] j = L / primes[i] j=L/primes[i] 对于情况 1 , j = 0 j = 0 j=0 , 对于情况2 , j = 1 j = 1 j=1
出现这两种状况时若对此时的 j × p r i m e s [ j ] j \times primes[j] j×primes[j] 标记则会出现错误
因为 L 和 U 的插值不超过 1 0 6 10^6 106 我们可以将每个 [L,U] 的数映射到下标为 [0,U-L] 的数组中 , 遍历数组即可得到答案
AC代码:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int inf = 0x3f3f3f3f ;
const int N = 1e6 + 10 , M = 46350 ;
int d[N] ;
LL primes[M] , st[M] , cnt ;
void get_primes(){
for(LL i = 2; i < M ; i ++ ) {
if(!st[i]) primes[cnt++] = i ;
for(LL j = 0 ; j < cnt && primes[j] < M / i ; j ++ ) {
st[ primes[j] * i ] = 1 ;
if( i % primes[j] == 0 ) break ;
}
}
}
int main(){
int l , r ;
get_primes() ;
while(~scanf("%d%d",&l,&r)){
memset(d,0,sizeof(d)) ;
for(LL i = 0 ; i < cnt ; i ++ ) { //筛除[L,U]中的合数
for(LL j = l / primes[i] ; primes[i] * j <= r ; j ++ ) {
if( j == 0 || j == 1 ) continue ;
if(primes[i] * j >= l )
d[primes[i] * j - l ] = 1;
}
}
if(l == 1) d[0] = 1 ; //特殊处理L == 1 的情况
LL cnt2 = 0 , resmax = -inf , resmin = inf ;
LL pre , th ;
pre = th = -1 ;
LL resminl , resminr , resmaxl , resmaxr ;
for(LL i = l ; i <= r ; i ++ ) { //遍历求答案
if(!d[i-l]) {
cnt2 ++ ;
pre = th ;
th = i ;
if(pre != -1 && th != -1 ) {
if( th - pre > resmax){
resmaxl = pre , resmaxr = th ;
resmax = th - pre ;
}
if( th - pre < resmin ){
resminl = pre , resminr = th ;
resmin = th - pre ;
}
}
}
}
if(cnt2 < 2 ) puts("There are no adjacent primes.") ;
else printf("%d,%d are closest, %d,%d are most distant.\n",resminl,resminr,resmaxl,resmaxr) ;
}
return 0 ;
}