Алгоритм Евклида
Безумно часто требуется вычислять наибольший общий делитель. Можно, конечно, делать как в школе: раскладывать числа на простые множители, искать пересечение множеств и перемножать все числа в результате. Но такой подход максимально неэффективен.
Здесь я рассмотрю алгоритмы быстрого и очень быстрого нахождения наибольшего общего делителя.
Наибольший общий делитель чисел и — число
Когда оба числа равны , результат не определен, так как подойдет любое число. Будем в таком случае считать, что . Тогда .
Тут надо сразу сказать важную вещь. Наибольший общий делитель существует не только для чисел, а для всего, что может делиться. Это определение, все дальнейшие утверждения и алгоритмы будут справедливы для любых коммутативных колец с единицей, в которых есть евклидова норма.
Несколько примеров таких колец. Целые числа и евклидова норма , кольца многочленов и евклидова норма , гауссовы числа и евклидова норма .
Для нахождения наибольшего общего делителя двух чисел можно применить алгоритм Евклида. Основан этот алгоритм на следующем факте
Для ускорения вычислений можно сразу вычитать столько, сколько возможно. Получаем формулу, которую уже можно использовать
Ну вот мы и получили алгоритм Евклида.
function gcd(int a, int b) -> int:
if b == 0:
return a
else:
return gcd(b, a % b)Можно избавиться от небольшого оверхеда в рекурсии, переписав через цикл
function gcd(int a, int b) -> int:
while b > 0:
a %= b
swap a, b
return aДавайте грубо оценим время работы алгоритма. Каждую итерацию мы берем остаток от деления наибольшего числа на наименьшее, поэтому наибольшее число уменьшается минимум в два раза.
Отсюда получается, что алгоритм работает за время .
Расширенный алгоритм Евклида
Быстрый алгоритм Евклида
Для быстрого вычисления наибольшего общего делителя двух чисел можно применить следующий факт