Question:
Task:
Find all primes in the range A to B ( 1 <= A <= B <= 10 ^ 12 ), provided B – A <= 10 ^ 6 . I've been racking my brains over this for 4 days already. There is a C ++ solution using the Sieve of Eratosthenes .
Solution:
#include <iostream>
#include <cstring>
using namespace std;
typedef long long ll;
const ll MAXN = 1e6 + 1;
int main() {
cin.tie(0); //Ускоряем cin
cout.tie(0); //Ускоряем cout
ll a, b;
cin >> a >> b; //Получаем числа
bool prime[MAXN], ans[MAXN]; //ans[i] - является ли число a + i простым
memset(prime, true, MAXN);
memset(ans, true, MAXN);
prime[0] = prime[1] = false;
//Оба вложенных цикла взяты из кода по ссылку (стандартная реализация решета Эратосфена)
ll n = MAXN - 1;
for (ll i = 2; i <= n; ++i) {
if (prime[i]) {
ll r = a % i;
r = (i - r) % i; //Что нужно прибавить к а, чтобы получить непростое число
if (a + r > i && r < MAXN) //Проверяем на выход из массива. Если убрать условие а + r > i, тогда алгоритм отмечает 2, 3, 5 как не простые
ans[r] = false;
if (i + r < MAXN && a + r + i > 1ll * i)
ans[i + r] = false;
for (ll j = i * i; j <= n; j += i) {
prime[j] = false;
if (a <= j && j - a < MAXN) //Если а < 10 ^ 6 (бех этой проверки не работает)
ans[j - a] = false;
if (j + r < MAXN)
ans[j + r] = false;
}
}
}
//Выводим результат
for (ll i = 0; i <= b - a; ++i) {
if (ans[i] && a + i >= 2)
cout << a + i << ' ';
}
}
Solution Description:
Find all primes on the segment [0; b – a] behind O (10 ^ 6 log log 10 ^ 6) , using the remainder of the division, transfer these primes to the segment [a; b].
Problem:
The solution does not work on some tests (i.e. the solution is incomplete ). Unfortunately, the tests are unknown.
Answer:
I began to conduct tests on large numbers and noticed that often 1-2 difficult ones fall. I don't know why, but replacing j = i * i
with j = 2 * i
fixed everything, and the program did not work for more than 40 ms.
Complete solution code:
#include <iostream>
#include <cstring>
using namespace std;
typedef long long ll;
const ll MAXN = 1e6 + 1;
ll max(ll a, ll b) {
return a > b ? a : b;
}
int main() {
//cin.tie(0); //Ускоряем cin
//cout.tie(0); //Ускоряем cout
ll a, b;
cin >> a >> b; //Получаем числа
bool prime[MAXN], ans[MAXN]; //ans[i] - является ли число a + i простым
memset(prime, true, MAXN);
memset(ans, true, MAXN);
prime[0] = prime[1] = false;
ll mmax = MAXN - 1;
for (ll i = 2; i <= mmax; ++i) {
if (prime[i]) {
ll r = a % i;
r = (i - r) % i; //Что нужно прибавить к а, чтобы получить непростое число
if (a + r > i && r < MAXN) //Проверяем на выход из массива. Если убрать условие а + r > i, тогда алгоритм отмечает 2, 3, 5 как не простые
ans[r] = false;
if (i + r < MAXN && a + r + i > i)
ans[i + r] = false;
for (ll j = 2 * i; j <= mmax; j += i) {
prime[j] = false;
if (a <= j && j - a < MAXN) //Если а < 10 ^ 6 (бех этой проверки не работает)
ans[j - a] = false;
if (j + r < MAXN) {
ans[j + r] = false;
}
}
}
}
//Выводим результат
for (ll i = 0; i <= b - a; ++i) {
if (ans[i] && a + i >= 2)
cout << a + i << ' ';
}
}