Наша цель определить последовательность действий,
которая сможет выяснить является ли некоторое целое число
составным или простым
с высокой степенью достоверности,
которую мы можем задавать.
И это должно быть сделано эффективно,
то есть должно быть легковычисляемо на любой машине.
Даже при увеличении входных данных
(в смысле нашего числа N)
всё должно работать быстро.
Пока мы поняли, что на самом нижнем уровне
нужно знать некоторый шаблон, под который подходят все простые числа
и не очень многие составные числа.
Однако, в предыдущем видео
была приведена демонстрация малой теоремы Ферма.
Она даёт нам очень интересную закономерность.
Для данного простого числа P
и какого-то другого целого числа A,
большего единицы и меньшего P,
мы знаем теперь, что P делит (A^P - A).
Мы записали это как A^P ≡ A mod P.
И это тот вид, в котором её обычно приводят.
Так как A и P не имеют общих делителей,
потому что P простое число, мы можем воспользоваться
правилом сокращения и записать это как
A^(P-1) ≡ 1 mod P.
Но помните, что мы можем так сделать только потому,
что наибольший общий делитель A и P равен 1.
Я сделал небольшую демонстрацию, чтобы мы сначала
просто посмотрели на это уравнение в действии.
Заметьте, что когда я указываю простое P, ответ всегда равен 1,
вне зависимости от того, как выбрано значение A.
Если же взять составное P, видно, что
ответ обычно не равен 1.
И каждый раз когда ответ не равен 1,
у нас есть "свидетель делимости".
Это доказывает, что выбранное P не может быть простым.
Это самая суть этой проверки.
Прежде чем углубиться в подробности, давайте вернёмся немного назад
и постоим структуру для нашей проверки,
используя шаблон, который я только что показал.
Итак, проверка начинается с подачи некоторого целого числа,
назовём его P, в качестве входных данных.
Далее мы выбираем случайное целое число A
меньшее P.
После чего мы можем спросить:
"Наибольший общий делитель A и P равен 1?"
Если нет, если наибольший общий делитель
A и P больше 1,
то у них есть общий множитель,
и мы доказали, что P составное,
так как у него есть делитель не равный 1.
В этом случае можно остановиться и закончить проверку.
Наш алгоритм выведет "составное".
Однако, если наибольший делитель равен 1, то можно задать следующий вопрос:
"A^(P-1) по модулю P равно 1?"
Если нет, у нас есть "свидетель делимости" P.
Мы можем остановиться и сказать: "Всё мы закончили, P составное."
В противном случае, если получилась единица,
тогда число должно быть простым, так?
Я запрограммировал эту последовательность действий.
Здесь слева проверка Ферма,
а справа наша старая проверка на простоту.
Я поместил её сюда,
так как нам уже известно, что она всегда работает правильно.
На первый взгляд кажется, что новая проверка работает.
Однако, я нашёл ошибку.
Я ввёл число 511 и проверка Ферма
говорит, что оно простое,
а проверка делением, что оно составное.
511 кажется простым с точки зрения проверки Ферма.
Но оно не простое.
Вернёмся к нашему уравнению
и посмотрим на то, что случилось.
Ну, это пример так называемого "псевдопростого" числа.
Это составное число.
Но есть определённые числа A, выбирая которые, мы получим 1.
Что снова неверно.
То есть эти числа A, которые приводят к тому, что для составного числа
получается единица, можно назвать "обманщиками",
потому что они обманывают нас, заставляя считать эти числа простыми.
Но заметьте, что если мы выбираем другие числа A,
кажется, что находится множество "свидетелей делимости"
вместо "обманщиков".
Поэтому нам, возможно, нужно вернуться немного назад
и применить тот же подход,
который мы использовали для проверки делимости.
Тогда мы просто повторяли проверку несколько раз,
постоянно выбирая новое случайное число.
Будем надеяться, что не выберем "обманщиков" все разы.
Понятно, что количество "обманщиков"
должно делить общий размер набора из которого мы выбираем числа.
Допустим, в худшем случае, половина выборов
или половина элементов в этом наборе могут быть "обманщиками".
Так как числа A выбираются случайно,
шанс найти "свидетеля делимости",
а это то, что нам нужно, не меньше одной второй.
После t подхов
вероятность того, что не будет найдено ни одного "свидетеля"
для составного числа
не больше чем 1/(2^t).
Так что после 20 попыток, шанс ошибочного определения
числа A как простого меньше чем один к миллиону.
То есть нам должно очень сильно не везти
при выборе случайных чисел A.
Каждый раз мы должны выбирать "обманщика".
Постарайтесь осознать это,
это очень значимо для понимания.
Вот здесь можно увидеть нашу проверку в действии
с увеличенным количеством попыток.
Кажется, работает идеально.
Заметим, что в худшем случае,
который, как мы знаем, случается,
когда мы подаём алгоритму простое число,
он выполняет максимально много вычислений,
проверка Ферма намного более эффективная, чем проверка делением.
Особенно потому, что число шагов
не растёт вместе с ростом входных данных.
Это ключевое отличие.
Мы задаём количество попыток и всё.
Нам никогда не нужно беспокоиться, что наш алгоритм
будет выполнять миллионы и миллионы шагов
как раньше.
Я имею в виду, что это самая что ни на есть прикладная математика.
Мы взяли шаблон, который кто-то открыл,
и сэкономили необъятное количество
вычислительных циклов.
Как бы то ни было, есть одна небольшая неприятность, или ошибка, в этой системе.
Сможете найти её?
