Как сито Эратосфена может быть реализовано за O (n) сложность времени? - PullRequest
0 голосов
/ 12 апреля 2020

Существует реализация этого алгоритма нахождения простых чисел до n в O(n*log(log(n)) сложности времени. Как мы можем достичь этого в O(n) сложности времени?

Ответы [ 2 ]

0 голосов
/ 12 апреля 2020

Вы можете выполнить Сито Эратосфена, чтобы определить, какие числа просты в диапазоне [2, n] в O(n) времени следующим образом:

  • Для каждого числа x в интервал [2, n], мы вычисляем минимальный простой множитель x. В целях реализации это легко сделать, сохранив массив --- скажем, MPF[] ---, в котором MPF[x] представляет минимальный простой коэффициент x. Первоначально вы должны установить MPF[x] равным нулю для каждого целого числа x. По мере выполнения алгоритма эта таблица будет заполнена.

  • Теперь мы используем for-l oop и выполняем итерацию от i = 2 до i = n (включительно). Если мы сталкиваемся с числом, для которого MPF[i] равно 0, то мы немедленно заключаем, что i является простым, поскольку оно не имеет наименьшего простого множителя. На этом этапе мы помечаем i как простое, вставляя его в список, и устанавливаем MPF[i] равным i. И наоборот, если MPF[i] делает не равным 0, то мы знаем, что i является составным с минимальным простым множителем, равным MPF[i].

  • На каждой итерации после проверки MPF[i] мы делаем следующее: вычисляем число y_j = i * p_j для каждого простого числа p_j, меньшего или равного MPF[i], и устанавливаем MPF[y_j] равным p_j ,

Это может показаться нелогичным - почему время выполнения O(n), если у нас есть два вложенных цикла? Ключевая идея заключается в том, что каждое значение установлено точно на единицу, поэтому время выполнения равно O(n). Этот веб-сайт предоставляет реализацию C ++, которую я привел ниже:

const int N = 10000000;
int lp[N+1];
vector<int> pr;

for (int i=2; i<=N; ++i) {
    if (lp[i] == 0) {
        lp[i] = i;
        pr.push_back (i);
    }
    for (int j=0; j<(int)pr.size() && pr[j]<=lp[i] && i*pr[j]<=N; ++j)
        lp[i * pr[j]] = pr[j];
}

Массив lp[] в приведенной выше реализации аналогичен MPF[], который я описал в мое объяснение. Кроме того, pr хранит список простых чисел.

0 голосов
/ 12 апреля 2020

Что ж, если алгоритм O (n * log (n)), вы, как правило, не можете сделать лучше без изменения алгоритма.

Сложность O (n * log (n)). Но вы можете торговать между временем и ресурсами: убедившись, что у вас есть O (log (n)) вычислительных узлов, работающих параллельно, можно было бы сделать это за O (n).

Надеюсь, я не сделал не делай свою домашнюю работу ...

...