Простые числа
От: DemAS http://demas.me
Дата: 14.02.08 06:39
Оценка:
Задача, найти алгоритм, который выдает перечень простых чисел в интервале от 1 до n.

Насколько я понял, если отбросить вероятностные алгоритмы и поиск по массиву известных чисел, то вараинтов решения всего два.

Первый — прямолинейный, для каждого k (1<=k<=n) найти остаток от деления от всех чисел в интервале 1..sqrt(n). Алгоритм не требовательный к памяти, но работает медленно. Грубо — O(n * sqrt(n)).
Второй — решето Эратосфена.

Вопрос 1 — а каково быстродействие данного алгоритма (bigO)?

Самая тупая приходящая в голову реализация — завести список целых чисел от 1 до n, и выкидывать из него составные не подходит из за требований к хранению данного списка в памяти.

Вопрос 2 — возможна ли реализация решета Эратосфена менее требовательная к памяти?

Я погуглил, и нашел реализацию которая ищет простые числа, называется решетом Эратосфена, но imho таковой не является. Поправьте меня если я не прав:

    #include <stdafx.h>
#include "eratosthenes.h"

/*************************************************************************
Процедура заполняет массив P простыми числами меньшими n,
элемент массива является последним, если следующий за ним
элемент равен 0.
*************************************************************************/
void eratosthenessieve(const int& n, ap::integer_1d_array& p)
{
    bool c;
    int i;
    int j;
    int k;
    int r;
    double s;

    if( n>200 )
    {
        r = ap::trunc(n/(log(double(n))-2)+1);
    }
    else
    {
        r = ap::trunc(1.6*n/log(double(n))+1);
    }
    p.setbounds(1, r);
    p(1) = 1;
    p(2) = 2;
    p(3) = 3;
    i = 4;
    do
    {
        p(i) = 0;
        i = i+1;
    }
    while(i<=r);
    j = 3;
    k = 3;
    do
    {
        i = 2;
        s = sqrt(double(k));
        c = true;
        do
        {
            i = i+1;
            if( p(i)>s )
            {
                p(j) = k;
                j = j+1;
                c = false;
            }
        }
        while(ap::trunc(double(k)/double(p(i)))*p(i)!=k&&c);
        k = k+2;
    }
    while(k<=n);
}


Как я понял эту реализацию:
1. j — указатель на следующее простое число в массиве. Нужен для того, чтобы после нахождения очередного простого числа мы знали куда его вставлять в целевой массив.
2. k — кандидиат на простое число (все нечетные числа). Хм... насколько я понимаю, это только первый цикл решета, дальше мы должны идти с шагом 3, 5 ....
3. каждого кандидата (k) мы пробуем нацело поделить на одно из известных простых чисел (trunc(double(k)/double(p(i)))*p(i)) до тех пор пока квадрат очередного известного простого числа не превысит кандидата (if( p(i)>s )). Дальше искать просто смысла нет.

Вопрос 3 — и где же здесь реализация решета? IMHO, это реализация первого способа — тупого перебора. Или я не прав?
... << RSDN@Home 1.2.0 alpha rev. 786>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.