Определение: |
Наибольшим общим делителем (англ. [math]\gcd[/math] — greatest common divisor) для двух целых чисел [math]a[/math] и [math]b[/math] называется наибольшее натуральное [math]d[/math], такое что [math]a[/math] делится на [math]d[/math] и [math]b[/math] делится на [math]d[/math]. Более формально,
[math]\gcd(a, b) =\max \left\{ d \mid a \equiv 0 \left(\bmod d\right), b \equiv 0 \left(\bmod d\right) \right\}[/math] |
Свойства НОД
Наибольший общий делитель существует и однозначно определён, если хотя бы одно из чисел [math]m[/math] или [math]n[/math] не ноль.
Понятие наибольшего общего делителя естественным образом обобщается на наборы из более чем двух целых чисел:
Определение: |
Наибольший общий делитель для целочисленного множества [math]A[/math] определяется как
[math]\gcd(A) = \max \left\{ d \mid \forall a_j \in A,\: a_j \equiv 0 \left(\bmod d \right)\right\}[/math] |
Существует определение НОД через разложение числа на простые множители:
Утверждение: |
Пусть [math]a[/math] и [math]b[/math] — натуральные числа. Тогда [math]\gcd(a, b) = p_1^{\min(\alpha_1, \beta_1)}\cdot p_2^{\min(\alpha_2, \beta_2)} \cdot \dotso \cdot p_k^{\min(\alpha_k, \beta_k)},[/math] где [math]p_j[/math] — делитель [math]a[/math] и [math]b[/math]. (Если [math]a[/math] не делится на [math]p_j,[/math] будем считать, что [math]p_j[/math] присутствует в разложении [math]a[/math] в [math]0[/math]-ой степени.) |
[math]\triangleright[/math] |
Разложим [math]a[/math] и [math]b[/math] на множители: пусть [math]a = p_1^{\alpha_1} \cdot p_2^{\alpha_2} \cdot \dotso \cdot p_k^{\alpha_k}, \:
b = q_1^{\beta_1} \cdot q_2^{\beta_2} \cdot \dotso \cdot q_k^{\beta_k}[/math], где [math]p_j, q_j[/math] — простые, а [math]\alpha_j, \beta_j[/math] — натуральные
(такие разложения существуют, по основной теореме арифметики). Без ограничения общности, можно считать, что [math]p_j = q_j, k = n[/math] (если это не так, сделаем соответствующие [math]\alpha[/math] и [math]\beta[/math] равными нулю).
Очевидно, что в таком случае [math]a[/math] и на [math]b[/math] делятся на [math]p = p_1^{\min(\alpha_1, \beta_1)}\cdot p_2^{\min(\alpha_2, \beta_2)} \cdot \dotso \cdot p_k^{\min(\alpha_k, \beta_k)} [/math]. Проверим его максимальность.
Пусть существует [math]q \gt p[/math], такое что [math]a[/math] и [math]b[/math] делятся на [math]q[/math]. Тогда оно необходимо будет раскладываться на те же простые множители, что и [math]p[/math].
Пусть [math]q = p_1^{\gamma_1}\cdot p_2^{\gamma_2} \cdot \dotso \cdot p_k^{\gamma_k} [/math]. Значит, существует [math]j \leqslant k : \min(\alpha_j, \beta_j) \lt \gamma_j[/math]. Из этого следует, что либо [math]\gamma_j \gt \alpha_j[/math], либо [math]\gamma_j \gt \beta_j[/math]. Но в первом случае, [math]q[/math] не окажется делителем [math]a[/math], а во втором — [math]b[/math]. Значит, такого [math]q[/math] не существует. |
[math]\triangleleft[/math] |
Связь с наименьшим общим кратным
Определение: |
Наименьшим общим кратным (англ. [math]\text{lcm}[/math] — least common multiple) для двух чисел [math]a[/math] и [math]b[/math] называется наименьшее натуральное число, которое делится на [math]a[/math] и [math]b[/math] без остатка. Более формально
[math]\text{lcm}(a, b) = \min \left\{ d \mid d \equiv 0 \left( \bmod a\right), d \equiv 0 \left( \bmod b\right) \right\}[/math] |
Существует представление НОК через разложение числа на простые множители:
Утверждение: |
Пусть [math]a[/math] и [math]b[/math] — натуральные числа. Тогда [math]\text{lcm}(a, b) = p_1^{\max(\alpha_1, \beta_1)}\cdot p_2^{\max(\alpha_2, \beta_2)} \cdot \dotso \cdot p_k^{\max(\alpha_k, \beta_k)}[/math] |
[math]\triangleright[/math] |
Доказательство полностью аналогично доказательству утверждения о НОД, с той лишь разницей, что мы заменяем [math]\min[/math] на [math]\max[/math], а знаки неравенств — на противоположные. |
[math]\triangleleft[/math] |
Наибольший общий делитель связан с наименьшим общим кратным следующим равенством:
Лемма: |
Пусть [math]a[/math] и [math]b[/math] — целые числа. Тогда [math]\gcd(a, b) \cdot \text{lcm}(a, b) = a \cdot b[/math]. |
Доказательство: |
[math]\triangleright[/math] |
По утверждению о НОД и утверждению о НОК, пользуясь тем, что [math]\max(\alpha, \beta) + \min(\alpha, \beta) = \alpha + \beta[/math], получаем нашу лемму. |
[math]\triangleleft[/math] |
Алгоритм Вычисления
Наивный алгоритм
В наивном методе, мы считаем, что нам известны разложения чисел [math]a[/math] и [math]b[/math] на простые множители.
// [math]p[/math] — множество простых чисел в разложении [math]a[/math]
// [math]q[/math] — множество простых чисел в разложении [math]b[/math]
// [math]\alpha[/math] — степени простых чисел в разложении [math]a[/math]
// [math]\beta[/math] — степени простых чисел в разложении [math]b[/math]
function naiveGcd(p, q, [math]\alpha[/math], [math]\beta[/math]):
gcd [math]\leftarrow[/math] 1
i, j [math]\leftarrow[/math] 0, 0
while i < p.length() and j < q.length():
if [math]p_i[/math] == [math] q_j[/math] :
t [math]\leftarrow[/math] min([math]\alpha_i[/math], [math]\beta_i[/math])
gcd = gcd [math]\cdot[/math] [math]p_i^t[/math]
else if [math]p_i[/math] < [math]q_j[/math] :
i += 1
else:
j += 1
return gcd
Корректность алгоритма следует из того, что он по сути просто делает пересечение двух упорядоченных массивов ([math]p[/math] и [math]q[/math]), только результат записывает не в массив, а агрегирует в переменной [math]\gcd[/math]. Асимптотика равна минимуму из длин массивов [math]p[/math] и [math]q[/math].
Стандартный алгоритм Евклида
Теорема: |
Пусть [math]a[/math] и [math]b[/math] — целые числа, не равные одновременно нулю, и последовательность чисел
- [math] a,\, b,\,r_1 \gt r_2 \gt r_3 \gt r_4 \gt \cdots \gt r_n[/math]
определена тем, что каждое [math]r_k[/math] — это остаток от деления предпредыдущего числа на предыдущее, а предпоследнее делится на последнее нацело, то есть
- [math]a = b \cdot q_0 + r_1[/math]
- [math]b = r_1 \cdot q_1 + r_2[/math]
- [math]r_1 = r_2 \cdot q_2 + r_3[/math]
- [math]\cdots[/math]
- [math]r_{k-2} = r_{k-1} \cdot q_{k-1} + r_k[/math]
- [math]\cdots[/math]
- [math]r_{n-1} = r_n \cdot q_n[/math]
Тогда [math]\gcd(a, b) = r_n[/math] — последний ненулевой член этой последовательности. |
Существование таких [math]r_1, r_2, \cdots[/math], то есть возможность деления с остатком [math]m[/math] на [math]n[/math] для любого целого [math]m[/math] и целого [math]n\ne 0[/math], доказывается индукцией по m.
Корректность этого алгоритма вытекает из следующих двух утверждений:
Лемма: |
Пусть [math]a = b\cdot q + r[/math], тогда [math]\gcd (a,b) = \gcd (b,r).[/math] |
Доказательство: |
[math]\triangleright[/math] |
- Пусть [math] k [/math] — любой общий делитель чисел [math] a [/math] и [math] b [/math], не обязательно максимальный, тогда [math] a = t_1 \cdot k [/math] ; [math] b = t_2 \cdot k [/math]; где [math] t_1 [/math] и [math] t_2 [/math] — целые числа из определения.
- Тогда [math] k [/math] также общий делитель чисел [math] b [/math] и [math] r [/math], так как [math] b [/math] делится на [math] k [/math] по определению, а [math]r = a - b \cdot q = (t_1 - t_2 \cdot q)\cdot k [/math] (выражение в скобках есть целое число, следовательно, [math] k [/math] делит [math] r [/math] без остатка)
- Обратное также верно и доказывается аналогично: пусть [math] k [/math] — любой общий делитель чисел [math] b [/math] и [math] r [/math], не обязательно максимальный, тогда [math] b = t_1 \cdot k [/math] ; [math] r = t_2 \cdot k [/math]; где [math] t_1 [/math] и [math] t_2 [/math] — целые числа из определения.
- Тогда [math] k [/math] также общий делитель чисел [math] a [/math] и [math] b [/math], так как [math] b [/math] делится на [math] k [/math] по определению, а [math]a = b \cdot q + r = (t_1 \cdot q + t_2)\cdot k [/math] (выражение в скобках есть целое число, следовательно, [math] a [/math] делит [math] a [/math] без остатка)
- Следовательно, все общие делители пар чисел [math] a [/math], [math] b [/math] и [math] b [/math], [math] r [/math] совпадают. Другими словами, нет общего делителя у чисел [math] a [/math], [math] b [/math], который не был бы также делителем [math] b [/math], [math] r [/math], и наоборот.
- В частности, максимальный делитель остается тем же самым. Что и требовалось доказать.
|
[math]\triangleleft[/math] |
Лемма: |
[math]\gcd (0,r) = r[/math] для любого ненулевого [math]r.[/math] |
Далее, оценим асимптотику работы алгоритма.
Теорема: |
Алгоритм Евклида работает за [math]O(\log \min (a, b))[/math] |
Доказательство этого факта[1] достаточно громоздкое, поэтому не будем приводить его здесь.
Проще сформулировать алгоритм Евклида так: если даны натуральные числа [math]a[/math] и [math]b[/math] и, пока получается положительное число, по очереди вычитать из большего меньшее, то в результате получится НОД.
Таким образом, реализация стандартного алгоритма Евклида, достаточно проста:
function euclideanGcd(a, b) :
while b [math]\neq[/math] 0 :
t [math]\leftarrow[/math] b
b [math]\leftarrow[/math] a mod b
a [math]\leftarrow[/math] t
return a
Мы получили очень простой алгоритм, который считает НОД за логарифмическое время. However, we can do better.
Двоичный алгоритм Евклида
Идея улучшения: давайте вместо долгого деления ограничимся вычитаниями и битовыми сдвигами.
Для начала, опишем еще несколько свойств [math]gcd[/math]:
Утверждение: |
Пусть [math]a[/math] и [math]b[/math] — натуральные числа, тогда
- [math]\gcd(2 \cdot a, 2 \cdot b) = 2 \cdot \gcd(a, b)[/math]
- [math]\gcd(2 \cdot a, 2 \cdot b + 1) = \gcd(a, 2 \cdot b + 1)[/math]
- [math]\gcd(2 \cdot a + 1, 2 \cdot b + 1) = \gcd(\left|a - b\right|, 2 \cdot b + 1)[/math]
|
[math]\triangleright[/math] |
Тривиальным образом следует из определения |
[math]\triangleleft[/math] |
Пользуясь этим, и утверждением о НОДе нуля, определим двоичный алгоритм Евклида (ниже будет дана рекурсивная реализация, для лучшей читаемости):
function binaryGcd(a, b) :
if a == b or b == 0 :
return a
if a == 0 :
return b
// первые два случая
if a mod 2 = 0 :
if b mod 2 = 0 :
return binaryGcd(a / 2, b / 2) [math]\cdot[/math] 2
else
return binaryGcd(a / 2, b)
// второй случай, только [math]a[/math] и [math]b[/math] поменяли местами
if b mod 2 = 0 :
return binaryGcd(a, b / 2)
// остается третий случай. На самом деле, мы можем оставлять справа и [math]a[/math], и [math]b[/math]
// поэтому давайте всегда оставлять меньшее
if a > b :
return binaryGcd((a - b) / 2, b)
return binaryGcd((b - a) / 2, a)
Корректность данного алгоритма следует из того, что он на каждом шаге делает эквивалентные преобразования НОД(это следует из утверждений о НОДе четных и нечетных и о НОДе нуля).
Можно показать[2], что этот алгоритм, в среднем на 60% более эффективен, чем классический.
Расширенный алгоритм Евклида
В стандартном алгоритме мы использовали следующее свойство: [math]\gcd(a, b) = \gcd(b, a \bmod b)[/math]. Воспользуемся им для того, чтобы решить следующую задачу: найти [math]x[/math] и [math]y[/math] такие, что [math]a \cdot x + b \cdot y = \gcd(a, b)[/math]. Пусть мы нашли пару [math]x_1, y_1: \: b \cdot x_1 + (a \bmod b) \cdot y_1 = \gcd(a, b)[/math].
Очевидно, что [math]a \bmod b = a - \lfloor \dfrac{a}{b}\rfloor \cdot b[/math]. Получаем: [math]b \cdot x_1 + (a \bmod b) \cdot y_1 = b \cdot x_1 + \left(a - \lfloor \dfrac{a}{b}\rfloor \cdot b\right) \cdot y_1 =
b \cdot \left(x_1 - \lfloor \dfrac{a}{b}\rfloor \cdot y_1\right) + a \cdot y_1 = a \cdot y_1 + b \cdot \left(x_1 - \lfloor \dfrac{a}{b}\rfloor \cdot y_1\right)[/math]. Следовательно, приходим к расширенному алгоритму Евклида:
// Алгоритм возвращает тройку [math]\gcd, x, y[/math]
function extendedGcd(a, b) :
if b == 0 :
return a, 1, 0
gcd, [math]x_1[/math], [math]y_1[/math] [math]\leftarrow[/math] extendedGcd(b, a mod b)
x [math]\leftarrow[/math] [math]y_1[/math]
y [math]\leftarrow[/math] [math]x_1[/math] - (a div b) [math]\cdot[/math] [math]y_1[/math]
return gcd, [math]x[/math], [math]y[/math]
Такое представление наибольшего общего делителя называется соотношением Безу, а числа [math]x[/math] и [math]y[/math] — коэффициентами Безу. Соотношение Безу является ключевым в доказательстве леммы Евклида и основной теоремы арифметики.
См. также
Примечания
Источники информации