Давайте немного изменим вопрос: как быстро вы можете сгенерировать простые числа между m и n и просто записать их в память?(Или, возможно, на RAM-диск.) С другой стороны, запомните диапазон параметров, как описано на странице проблемы: m и n могут достигать миллиарда, а nm - не более миллиона.
IVlad и Brian большинство конкурентных решений, даже если это правда, что более медленное решение может быть достаточно хорошим.Сначала сгенерируйте или даже предварительно вычислите простые числа меньше, чем sqrt (миллиард);их не очень много.Затем выполните усеченное сито Эратосфена: создайте массив длиной n-m + 1, чтобы отслеживать состояние каждого числа в диапазоне [m, n], причем первоначально каждое такое число помечается как простое число (1).Затем для каждого предварительно вычисленного простого числа p выполните цикл, который выглядит следующим образом:
for(k=ceil(m/p)*p; k <= n; k += p) status[k-m] = 0;
Этот цикл отмечает все числа в диапазоне m <= x <= n как составные (0), если они кратныиз р.Если это то, что IVlad подразумевал под «довольно некрасивым», я не согласен;Я не думаю, что это так плохо. </p>
На самом деле, почти 40% этой работы только для простых чисел 2, 3 и 5. Есть хитрость, чтобы объединить сито для нескольких простых чисел синициализация массива статуса.А именно, шаблон делимости на 2, 3 и 5 повторяет мод 30. Вместо инициализации массива со всеми 1, вы можете инициализировать его повторяющимся шаблоном 010000010001010001010001000001. Если вы хотите быть еще более режущим, вы можете продвинуться впередk на 30 * p вместо p, и отмечать только кратные значения в одном и том же шаблоне.
После этого реалистичное повышение производительности будет включать такие шаги, как использование битового вектора вместо массива символов для сохранения ситаданные в кэш-памяти.И инициализировать битовый вектор слово за словом, а не бит за битом.Это действительно запутанно, а также гипотетически, так как вы можете быстрее генерировать простые числа, чем использовать их.Базовое сито уже очень быстрое и не очень сложное.