Фонтаны с «сбитым» таймером
Условие
В школьном дворе поставили два фонтана с таймерами.
- Фонтан A включается ровно в моменты времени 0, m, 2m, 3m, ... минут от начала отсчёта.
- Фонтан B должен был включаться в 0, p, 2p, ... минут, но мастер случайно сдвинул таймер так, что первое включение будет через 1 минуту, а дальше каждые p минут: 1, 1+p, 1+2p, ...
Найди самый ранний момент времени (в минутах от начала отсчёта), когда оба фонтана включатся одновременно. Если такого момента не бывает — выведи -1.
Важно: ответ может быть больше, чем помещается в 32-битный тип (как на олимпиадах), то есть может понадобиться 64-битная арифметика.
Формат ввода
В одной строке записаны два целых числа m и p.
Формат вывода
Выведи одно целое число — минимальное t >= 0, такое что:
tкратноm,tдаёт остаток1при делении наp.
Если такого t не существует, выведи -1.
Ограничения
1 <= m <= 10^92 <= p <= 10^9- лимит времени: 1 секунда
- лимит памяти: 256 МБ
Пример
Ввод:
4 7
Вывод:
8
Пояснение: фонтан A включается в 0,4,8,12,... а фонтан B — в 1,8,15,... Первый общий момент — 8.
Как решать — идея подхода
Приём: Расширенный алгоритм Евклида (обратный элемент по модулю)
Ключевое наблюдение: общий момент t должен одновременно быть кратен m и давать остаток 1 по модулю p. Если t кратен m, то t = m*k для некоторого целого k. Подставляем во второе условие:
t = m*k и t % p = 1 => m*k ≡ 1 (mod p).
Это линейное сравнение. Оно имеет решение тогда и только тогда, когда gcd(m, p) делит 1, то есть когда gcd(m, p) = 1. В этом случае у числа m есть обратный элемент по модулю p.
Почему работает расширенный Евклид: он находит такие x и y, что x*m + y*p = gcd(m,p). Если gcd = 1, получаем x*m + y*p = 1, значит x*m ≡ 1 (mod p), то есть x — это и есть обратный к m по модулю p.
План решения:
- Посчитай g = gcd(m, p). Если g != 1, выведи -1.
- Запусти расширенный Евклид для (m, p), получи коэффициент x из
x*m + y*p = 1. - Приведи x к остатку:
k = x % p(минимальный k >= 0). - Ответ:
t = m * k.
Сложность: O(log(min(m,p))) по времени, памяти почти не нужно.
Частая грабля: забыть проверку gcd(m,p)=1 и пытаться «найти обратный» всегда — тогда на некоторых тестах решения не существует. Также не перепутай: нужен обратный для m по модулю p, а не наоборот.
Разберись руками
Фонтан A включается каждые 4 минуты: 0, 4, 8, 12, ... Фонтан B включается в 1 минуту и дальше каждые 7 минут: 1, 8, 15, ... Нужно найти самое раннее общее включение.
- Отметь на ленте от 0 до 30 все моменты, когда включается фонтан A (кратные 4).
- Теперь на той же ленте 0..30 отметь моменты, когда включается фонтан B. Это числа, которые при делении на 7 дают остаток 1.
- Посмотри на два отмеченных набора и найди самый маленький общий момент времени. Какое это число?
Идея: Сначала выпиши (или проверяй) моменты первого фонтана как кратные его шагу, а моменты второго — как числа с нужным остатком при делении на его шаг. Самый ранний общий момент — первое число, которое подходит сразу под оба условия; если такого числа вообще не находится, значит расписания «не совпадают» и ответа нет.
Решить задачу с автопроверкой на Python →
Куда дальше
- Школьный этап ВсОШ по информатике — как устроен первый этап и план подготовки за четыре недели
- БВИ и льготы при поступлении — какой диплом что даёт и сколько лет он действует
- Перечневые олимпиады по информатике — олимпиады перечня Минобрнауки, их уровни и что нужно к диплому