Теоретический материал (Ханойские башни)
2. Наибольший общий делитель
Всех вас в свое время на уроках математики учили находить наибольший общий делитель двух чисел. Для этого нужно было первым делом разложить их на простые множители. Сейчас мы рассмотрим другой алгоритм, который и реализовывать проще, да и работает он быстрее. Он основан на следующем свойстве НОД:
НОД(a,b)=НОД(a-b,b) при a≥b.
Это свойство несложно доказать. Если d – делитель чисел a и b, то на d делится и разность чисел a и b. Обратно, если d является делителем чисел a-b и b, то и их сумма (a-b)+b=a делится на d. Таким образом, всякий общий делитель чисел a и b является общим делителем чисел a-b и b, и наоборот. Поэтому и наибольшие делители у этих пар чисел совпадают.
Пользуясь этой формулой, можно легко написать рекурсивную функцию для вычисления НОД. Надо лишь не забывать про терминальное условие.
function NOD (a,b : integer) : integer;
begin
if a<b then swap(a,b); {переставляем большее число
на первое место}
if b=0 then NOD:=a {терминальное условие: НОД(a,0)=a}
else NOD:=NOD(a-b,b);
end;
Работу алгоритам можно еще ускорить, если воспользоваться формулой
НОД(a,b)=НОД(a mod b,b).
Алгоритм вычисления НОД по этой формуле называют алгоритмом Евклида.
Заметим, что эта формула верна для всех a и b, но если a<b, то a mod b = a и формула вырождается в тривиальную. Чтобы обойтись без процедуры swap, можно пользоваться формулой НОД(a,b)=НОД(b, a mod b).
function NOD (a,b : integer) : integer;
begin
if b=0 then NOD:=a {терминальное условие: НОД(a,0)=a}
else NOD:=NOD(b, a mod b);
end;