подход
Допустим, у вас есть число n
, которое увеличивается до 10 18 , и вы хотите его разложить на множители. Поскольку это число может быть как единичным, так и равным 10 18 , все время оно может быть как простым, так и составным, таков мой подход -
- Используя тестирование простоты Миллера Рабина , убедитесь, что число составное.
- Факторизация
n
с использованием простых чисел до 10 6 , которые можно рассчитать с использованием сита Эратосфена .
Теперь обновленное значение n
таково, что оно имеет простые множители только выше 10 6 , и поскольку значение n
все еще может быть равно 10 18, мы заключаем, что число либо простое, либо имеет ровно два простых фактора (не обязательно различающихся).
- Запустите Миллера Рабина снова, чтобы убедиться, что число не простое.
- Используйте Алгоритм Полларда , чтобы получить один простой множитель.
Теперь у вас есть полная факторизация.
Давайте посмотрим на сложность времени вышеупомянутого подхода:
- Миллер Рабин принимает
O(log n)
- Сито Эратосфена занимает
O(n*log n)
- Реализация Полларда, которой я поделился, занимает
O(n^0.25)
Сложность времени
Шаг 2 занимает максимальное время, равное O(10^7)
, что, в свою очередь, является сложностью вышеуказанного алгоритма. Это означает, что вы можете найти факторизацию за секунду практически для всех языков программирования.
Космическая сложность
Пробел используется только на шаге 2, где реализовано сито, и равен O(10^6)
. Опять же, очень практично для этой цели.
Осуществление
Полный код реализован в C++14
. В коде есть скрытая ошибка. Вы можете раскрыть это в следующем разделе или перейти к задаче;)
Ошибка в коде
Вызов
Дайте мне значение n
, если оно есть, когда общий код приводит к неправильной простой факторизации.
Бонус
Сколько таких значений n
существует?
намек
Решение
Бонусное решение