Редакция для Совместимые шестерёнки
Submitting an official solution before solving the problem yourself is a bannable offence.
Автор:
1. Идея
Нужно проверить, имеют ли числа a и b общий делитель больше 1.
Если такого делителя нет, то числа взаимно простые, а значит шестерёнки считаются совместимыми.
Это ровно означает, что их наибольший общий делитель равен 1.
Значит задача сводится к вычислению НОД(a, b):
- если
НОД(a, b) = 1, выводимYES; - иначе выводим
NO.
Для нахождения НОД удобно использовать алгоритм Евклида.
2. Наблюдения
Наблюдение 1
По условию шестерёнки совместимы тогда и только тогда, когда у чисел a и b нет общего делителя больше 1.
Это стандартное определение взаимной простоты:
6и35— взаимно простые, потому что их НОД равен1;12и18— не взаимно простые, потому что их НОД равен6.
Наблюдение 2
Алгоритм Евклида позволяет быстро находить НОД двух чисел с помощью повторения операции:
- заменяем пару
(a, b)на(b, a % b), - пока
bне станет равно0.
Когда b = 0, текущее значение a и есть НОД исходных чисел.
Наблюдение 3
Ограничения до 10^18 довольно большие, поэтому перебирать делители нельзя.
Но алгоритм Евклида работает очень быстро даже для таких чисел.
3. Алгоритм
- Считать числа
aиb. - Пока
b != 0:- вычислить остаток
r = a % b; - присвоить
a = b; - присвоить
b = r.
- вычислить остаток
- После завершения цикла в
aхранится НОД исходных чисел. - Если
a == 1, вывестиYES, иначе вывестиNO.
4. Почему это работает
Основа решения — свойство НОД:
НОД(a, b) = НОД(b, a % b).
Почему это верно:
- любой общий делитель чисел
aиbделит и числоa - k * b, а значит делит остатокa % b; - наоборот, любой общий делитель чисел
bиa % bделит и числоa, потому чтоaможно представить какb * k + (a % b).
Значит множество общих делителей у пар (a, b) и (b, a % b) одинаковое, а значит одинаков и наибольший общий делитель.
Мы повторяем это преобразование, пока второе число не станет нулём.
Когда получаем пару (a, 0), НОД равен a, потому что НОД числа и нуля — это само число.
После этого остаётся только проверить:
- если НОД равен
1, общих делителей больше1нет, значит ответYES; - если НОД больше
1, такой общий делитель существует, значит ответNO.
5. Сложность
Алгоритм Евклида работает за O(log(min(a, b))).
Память: O(1).
6. Код на C++17
#include <iostream>
using namespace std;
int main() {
long long a, b;
cin >> a >> b;
while (b != 0) {
long long r = a % b;
a = b;
b = r;
}
if (a == 1) {
cout << "YES\n";
} else {
cout << "NO\n";
}
return 0;
}
7. Код на Python 3
a, b = map(int, input().split())
while b != 0:
a, b = b, a % b
if a == 1:
print("YES")
else:
print("NO")
Комментарии