Источник задачи: региональный этап Олимпиады им. М.В. Келдыша, 2025, задача A.
Что дано
У комиссии есть мангал с начальной температурой t. Готовят два вида шашлыка:
| Вид | Нужна температура ≥ | После готовки температура падает на |
|---|---|---|
| 1 | a | x |
| 2 | b | y |
Порции можно готовить в любом порядке, общее число порций не ограничено. Задача — приготовить как можно больше порций суммарно с учётом того, что перед каждой новой порцией температура мангала должна быть не меньше её порога. Между порциями температура может уйти в ноль или в минус — это допустимо, ограничение проверяется только перед началом готовки очередной порции.
Ограничения
- ,
- Ответ может превысить , поэтому арифметику вести в 64-битных целых (
long longв C++, обычныйintв Python).
Формат ввода
Пять натуральных чисел, каждое в отдельной строке: t, a, b, x, y (именно в таком порядке).
Формат вывода
Одно целое число — максимальное число порций.
Примеры
| # | t | a | b | x | y | Ответ |
|---|---|---|---|---|---|---|
| 1 | 10 | 3 | 4 | 2 | 1 | 8 |
| 2 | 1 | 10 | 10 | 1 | 1 | 0 |
| 3 | 28 | 14 | 5 | 2 | 4 | 10 |
Разберём первый пример руками
t = 10, a = 3, x = 2, b = 4, y = 1
Что это значит:
- Мангал изначально горячий (10°).
- Вид 1 требует 3°, уносит 2° (то есть «охлаждает сильно», но порог низкий).
- Вид 2 требует 4°, уносит 1° (порог выше, но охлаждает мягко).
Попробуем стратегию «чередуем вслепую»: вид 1, вид 2, вид 1, вид 2…
| Шаг | Температура перед | Вид | После |
|---|---|---|---|
| 1 | 10 | 1 | 8 |
| 2 | 8 | 2 | 7 |
| 3 | 7 | 1 | 5 |
| 4 | 5 | 2 | 4 |
| 5 | 4 | 1 | 2 |
| 6 | 2 | ? | 2 < 3 и 2 < 4 — ничего |
Итого — 5 порций. Неплохо, но ответ, как сейчас увидим, 8.
Попробуем «сначала все виды 2, потом виды 1»:
| Шаг | Темп. перед | Вид | После |
|---|---|---|---|
| 1 | 10 | 2 | 9 |
| 2 | 9 | 2 | 8 |
| 3 | 8 | 2 | 7 |
| 4 | 7 | 2 | 6 |
| 5 | 6 | 2 | 5 |
| 6 | 5 | 2 | 4 |
| 7 | 4 | 2 | 3 |
| 8 | 3 | 1 | 1 |
| 9 | 1 | ? | 1 < 3 и 1 < 4 — ничего |
Итого — 8 порций. Вот оно.
Интуиция, которая только что появилась в голове: выгодно сначала готовить тот вид, который охлаждает мангал меньше. У нас это вид 2 — он уносит всего 1° против 2° у вида 1. Каждая «единица охлаждения» — это потенциальная потеря будущих порций. Лучше тратить температуру по чайной ложке, чем сразу большими порциями.
Идея решения: жадность по минимальному охлаждению
Алгоритм в одну фразу:
Сначала готовим максимальное число порций того вида, у которого меньше охлаждение. Затем — максимальное число порций другого вида.
Чтобы не возиться с двумя случаями, договоримся: вид 1 у нас всегда экономный (тот, что меньше охлаждает). Если в условии оказалось наоборот — просто поменяем виды местами, ответ от этого не изменится. Тогда план такой:
- Готовим столько вида 1, сколько позволяет температура.
- Готовим столько вида 2, сколько позволяет оставшаяся температура.
- Сумма — ответ.
Почему жадность работает?
Температура — общий ресурс. Каждая порция его тратит. Чем меньше порция тратит — тем больше таких порций в целом помещается в один и тот же мангал. Значит, «экономный» вид всегда эффективнее: из одной и той же температуры его порций получится больше, чем «прожорливого».
Поэтому логика простая: сначала выжимаем максимум из экономного, остатки отдаём прожорливому. Если сделать наоборот — прожорливый вид сожжёт температуру, которой хватило бы на несколько порций экономного. Эту потерю уже не вернуть — пустая потраченная температура обратно не появляется.
Сколько порций одного вида можно приготовить из температуры T?
Допустим, есть температура , порог и охлаждение . Если — не приготовим ничего, нечего и считать. Если — одну порцию точно сделаем, после неё останется .
Дальше думаем так: над порогом у нас «лишних» градусов сверх минимума. Каждая следующая порция отъедает от этого запаса по . Сколько раз помещается в — столько ещё порций мы и приготовим (округление вниз, потому что недоеденный кусок нам не помогает). Плюс самая первая, которая помещается «бесплатно».
Итого формула одной строкой:
Округление вниз — это обычное целочисленное деление: // в Python, / для положительных long long в C++.
Решение: псевдокод
ввести t, a, b, x, y
# Хотим, чтобы x <= y (вид 1 — экономный)
если x > y:
поменять местами (a, x) и (b, y)
# Считаем, сколько порций вида 1 готовим
# (// — целочисленное деление с округлением вниз)
если t >= a:
k1 = (t - a) // x + 1
t = t - k1 * x
иначе:
k1 = 0
# Считаем, сколько порций вида 2 готовим из оставшейся t
если t >= b:
k2 = (t - b) // y + 1
иначе:
k2 = 0
вывести k1 + k2
Это — несколько арифметических операций.
Код решения
Переключи вкладку, чтобы посмотреть второй язык. В Python про переполнение int думать не надо — он неограниченной точности. В C++ обязателен long long везде: значения до , в int не поместятся.
Проверим на всех примерах из условия
Пример 1
t=10, a=3, x=2, b=4, y=1
- , меняем: теперь .
- : . .
- : .
- Ответ: 7 + 1 = 8 ✓
Пример 2
t=1, a=10, b=10, x=1, y=1
- , меняем или нет — всё равно.
- : .
- : .
- Ответ: 0 ✓
Пример 3
t=28, a=14, b=5, x=2, y=4
- , не меняем.
- : . .
- : .
- Ответ: 8 + 2 = 10 ✓
Всё сходится.
Крайние случаи, на которых можно споткнуться
Эти случаи тесты олимпиады почти наверняка проверяют. Перед отправкой убедись, что код их обрабатывает.
1. Изначально холодный мангал
t=5, a=10, b=10, x=1, y=1
Ответ — 0. Если посчитаешь (или что-то странное при переполнении) — значит забыл проверить и . В коде выше проверка есть.
2. Температура может стать сильно отрицательной
t=100, a=1, b=100, x=1000000000000, y=1
- , меняем: .
- . .
- .
- Ответ: 2. Температура после: . Это не проблема — ограничение проверялось до готовки.
3. Оба вида с одинаковым охлаждением
Допустим . Тогда порядок не важен, но по коду ложно, значит не меняем. Готовим сначала вид 1. Если — начнём с вида 1 (у которого ниже порог), потом добьём вид 2 — это тоже оптимально, так как при равном охлаждении работает любая разумная стратегия.
Проверь сам: → ожидаемый ответ: , , (так как ). Итого 5.
Альтернатива: сначала вид 2. , , . Итого 5. Одно и то же.
4. Границы ограничений
→ , , . Ответ: 1. long long вмещает ~, так что запас огромен.
Типичные ошибки
-
intвместоlong longв C++. Значения до , вint(макс. ~) не поместятся. В Java — использоватьlong, а неint. -
Забыл поменять и местами, когда . Частая ошибка: меняют только и , но не и . Порог привязан к виду — если меняешь охлаждение, меняй и порог.
-
Неверная формула для количества порций. Типичный баг: (без
+1). Тогда упустишь одну порцию в нижней границе. Проверяй: если , то (без+1) — но одна порция ведь помещается ()! Правильно: . -
Деление в Python через
/вместо//. В Python 3/— это float-деление, оно вернёт7.0вместо7. Используй//для целого. -
Проверка
t > aвместоt >= a. При одна порция помещается: перед готовкой температура ровно , условие «≥ » выполняется. -
Моделирование «по одной порции» в цикле. Теоретически работает, но при и цикл сделает итераций — это секунды или минуты, а дают 1 секунду на тест. Формула — , цикл — . Не рассчитывай на лимит времени — используй формулу.
Анализ сложности
- Время: . Несколько арифметических операций, не зависящих от значений переменных.
- Память: .
Что ещё полезно потренировать
Задачи с похожей идеей — «жадный выбор по наименее затратному варианту» (в олимпиадной классификации: greedy + exchange argument):
- Codeforces 230A «Dragons» — сортировка драконов по силе, жадный подход к порядку поглощения. Базовый пример жадности.
- Codeforces 137B «Permutation» — жадность по разности между массивом и оптимальной перестановкой.
- Codeforces 556A «Case of the Zeros and Ones» — жадное сокращение «01» и «10» пар.
- acmp.ru задача 186 «Два мешка» — жадный выбор, аналогичная конструкция.
После решения 3–5 таких задач (разными способами) интуиция «когда работает жадность и как её доказать через exchange argument» закрепляется — и следующая «греди» задача на олимпиаде решается за минуты.
Итого
- Идея: жадно, сначала вид с меньшим охлаждением, пока можно, потом другой.
- Формула количества порций из температуры с порогом и охлаждением :
- Сложность: .
- Ловушки: переполнение
int(нуженlong long), off-by-one в формуле (не забыть+1), забыть поменять пары и одновременно.