先線性篩出所有質數(關於線性篩,請右轉 HERE (選了篇比較好懂的博客) ),然後對所有鄰質數對進行處理。爲了方便描述,我們設一對鄰質數的差爲Ki,很明顯,Ki > 150時是毫無用處的(因爲輸入中兩個數最極端的差爲150),並且,對於每個小於等於150的Ki,只用保留較大質數小於等於150的所有鄰質數與大於150的第一對鄰質數。
有點拗口 (語文沒學好T-T) 也就是說,Ki大於150的,除了第一個,其他都不要了,因爲它們肯定不及第一個優(求的是x的最小值嘛),但是留下的都有價值 (看看代碼再仔細想想就知道了)。
如果沒聽懂,再結合註釋理解理解吧
#include<cstdio>
#include<vector>
using namespace std;
#define si 13626407
//最大的有效質數是這個,輸出max(a[i][j])得到的(節約空間,人人有責)
int T;
int A, B, sum;//sum爲 已取完所有 有效素數 的Ki有幾個
bool p[si + 5];//加5免得越界
int v[887319], tot; // 1~si範圍內質數的個數+5 tot存儲目前素數個數
bool c[155];//判斷第一個大於150的並且差爲Ki的有沒有出現
vector<int> a[155];//a[Ki]存儲所有差爲Ki有效的鄰質數(較小的那個)
inline void init(){//線性篩素數
p[1] = 1;//1不是素數
int t;
for ( int i = 2; i <= si; ++i ){
if ( !p[i] ){
v[++tot] = i;
if ( i <= 150 ){//開始時沒加,但也可以過,數據比較水
a[0].push_back(i);
}else{
if ( !c[0] ){
c[0] = 1;
a[0].push_back(i);
}
}
if ( i != 2 ){
if ( i <= 150 ) a[i - t].push_back(t);
else{
if ( i - t <= 150 && !c[i - t] ){
c[i - t] = 1;
a[i - t].push_back(t);
sum++;
}
}
}
t = i;
}
if ( sum >= 75 ) break; // Ki只可能是偶數(因爲質數除2外都是奇數,奇數減奇數爲偶數) 因此只有 150 個(當然了,除2、3外,但是這裏2和3不計入sum)
for ( int j = 1; j <= tot; ++j )
if ( i * v[j] <= si ) p[i * v[j]] = 1;
else break;
}
}
int main(){
init();
scanf( "%d", &T );
for ( int I = 1; I <= T; ++I ){
scanf( "%d%d", &A, &B );
if ( A > B ){
int t(A); A = B; B = t;//如果A > B 就交換 使 A <= B
}
int ans(-1);
for ( int i = 0; i < a[B - A].size(); ++i ){//在所有差爲B - A的質數對中找第一個滿足條件的數
if ( A <= a[B - A][i] ){
ans = a[B - A][i] - A;
break;
}
}
printf( "Case %d: %d\n", I, ans );
}
return 0;
}
撒花(^-^)