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