добавлено: 10 Jun 2008 17:54 Алгоритм Евклида нахождения НОД (наибольшего общего делителя)Даны два целых неотрицательных числа ![]() ![]() ![]() ![]() Когда оно из чисел равно нулю, а другое отлично от нуля, их наибольшим общим делителем, согласно определению, будет это второе число. Когда оба числа равны нулю, результат не определён (подойдёт любое бесконечно большое число), мы положим в этом случае наибольший общий делитель равным нулю. Поэтому можно говорить о таком правиле: если одно из чисел равно нулю, то их наибольший общий делитель равен второму числу. Алгоритм Евклида, рассмотренный ниже, решает задачу нахождения наибольшего общего делителя двух чисел Данный алгоритм был впервые описан в книге Евклида "Начала" (около 300 г. до н.э.), хотя, вполне возможно, этот алгоритм имеет более раннее происхождение. АлгоритмСам алгоритм чрезвычайно прост и описывается следующей формулой: Реализацияint gcd (int a, int b) { if (b == 0) return a; else return gcd (b, a % b); } Используя тернарный условный оператор C++, алгоритм можно записать ещё короче: int gcd (int a, int b) { return b ? gcd (b, a % b) : a; } Наконец, приведём и нерекурсивную форму алгоритма: int gcd (int a, int b) { while (b) { a %= b; swap (a, b); } return a; } Доказательство корректностиСначала заметим, что при каждой итерации алгоритма Евклида его второй аргумент строго убывает, следовательно, посколько он неотрицательный, то алгоритм Евклида всегда завершается. Для доказательства корректности нам необходимо показать, что Покажем, что величина, стоящая в левой части равенства, делится на настоящую в правой, а стоящая в правой — делится на стоящую в левой. Очевидно, это будет означать, что левая и правая части совпадают, что и докажет корректность алгоритма Евклида. Обозначим Далее, разложим остаток от деления Но тогда отсюда следует: Итак, вспоминая утверждение Воспользуемся теперь следующим простым фактом: если для каких-то трёх чисел ![]() ![]() Итак, мы провели половину доказательства: показали, что левая часть делит правую. Вторая половина доказательства производится аналогично. Время работыВремя работы алгоритма оценивается теоремой Ламе, которая устанавливает удивительную связь алгоритма Евклида и последовательности Фибоначчи: Если Более того, можно показать, что верхняя граница этой теоремы — оптимальная. При Учитывая, что числа Фибоначчи растут экспоненциально (как константа в степени НОК (наименьшее общее кратное)Вычисление наименьшего общего кратного (least common multiplier, lcm) сводится к вычислению Таким образом, вычисление НОК также можно сделать с помощью алгоритма Евклида, с той же асимптотикой: int lcm (int a, int b) { return a / gcd (a, b) * b; } (здесь выгодно сначала поделить на Литература
|