A
質問の意味:
間隔が与えられた場合[L、R] [L、R][ L 、R ]、この区間で隣接する差が最小と最大の素数のペアを尋ねます。
データ範囲:1≤L<R≤2147483647、R −L≤10 6 1 \ leq L <R \ leq 2147483647、RL \ leq10 ^ 61≤L<R≤2 1 4 7 4 8 3 6 4 7 、R−L≤1 06
回答:
-
1≤L<R≤21474836471\ leq L <R \ leq2147483647を検討してください1≤L<R≤2 1 4 7 4 8 3 6 4 7の場合、直接線形ふるいを実行してはなりません。
しかし、あなたが知ることができるのはRRですR内のすべての合成数の素因数は、R \ sqrt {R}を超えません。R 。 -
1 0 6 10 ^ 6の範囲を考慮してください1 06.より直感的なアイデアは、最初にR \ sqrt {R}を前処理することです。Rすべての素数を入力し、
これらの素数を使用して区間[L、R] [L、R]を除外します。[ L 、Rのすべての合成数]。最後に、[L、R] [L、R]を取得できます[ L 、R ]のすべての素数は隣接して比較できます。 -
ふるい素数の操作を思い出してください。
プライムプライム決定された各素数についてp r i m e、からi = 2×primei = 2 \ timesprime私=2××p r i m eが始まり、iii以primeプライムp r i m eが増加し始め、iiiがnn以下nおよびトラバースされたすべての番号は、合成数でマークされます。Ehrlichふるい法は、次のシリーズを通じて時間計算量を証明できます。O(nloglogn)O(n \ log \ log n)O (nlo glo gn )。
この質問は、2 ∗プライム2 *プライムからふるいの考えを渡すことができます2∗p r i m eは[L、R] [L、R]から始まります[ L 、R ]の間のすべての番号は、合成数でマークされています。
すべてのふるい位置が[L、R] [L、R]にあることを確認するため[ L 、R ]、
すべてiii的初始素最大((L +素数-1)/素数∗素数、2×素数)max((L +素数-1)/素数*素数、2 \回素数)m a x ((L+p r i m e−1 )/ p r i m e∗p r i m e 、2××p r i m e )。 -
この時点で、この質問に合格することができます。
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
ll L, R;
const int N = 1e6 + 10;
int pri[N], cnt = 0;
bool st[N];
void xs(int n) {
st[0] = st[1] = true;
for(int i = 2; i <= n; ++i) {
if(!st[i]) pri[++cnt] = i;
for(int j = 1; j <= cnt && i <= n / pri[j]; ++j) {
st[i * pri[j]] = true;
if(i % pri[j] == 0) break;
}
}
}
int p[N], act;
int ST[N];
void solve() {
act = 0;
int r = sqrt(R);
for(int j = 1; j <= cnt && pri[j] <= r; ++j) {
ll c = (L + pri[j] - 1) / pri[j];
while(c < 2) ++c;
ll fir = c * pri[j];
for(ll i = fir; i <= R; i += pri[j]) ST[i - L] = 1;
}
for(int i = 0; i <= R - L; ++i) {
if(ST[i]) continue;
if(i + L < N && st[i + L]) continue;
p[++act] = i + L;
}
if(act < 2) puts("There are no adjacent primes.");
else {
int mx = 2, mn = 2;
for(int i = 3; i <= act; ++i) {
if(p[mx] - p[mx - 1] < p[i] - p[i - 1]) mx = i;
if(p[mn] - p[mn - 1] > p[i] - p[i - 1]) mn = i;
}
printf("%d,%d are closest, %d,%d are most distant.\n", p[mn - 1], p[mn], p[mx - 1], p[mx]);
}
for(int i = 0; i <= R - L; ++i) ST[i] = 0;
}
int main()
{
xs(N - 1);
while(~scanf("%lld%lld", &L, &R)) solve();
return 0;
}