Купон «округлить вниз»
Условие
В школьном магазине ценники странные: все любят, когда цена делится на число a.
У Миши есть ровно один купон. Купон можно применить к одному товару (или не применять вовсе). Если купон применён к товару с ценой p, то на кассе за него возьмут самую большую цену, не превосходящую p и кратную a. То есть заплатят p - (p mod a).
Помоги Мише заплатить как можно меньше.
Формат ввода
В первой строке записаны два целых числа n и a — количество товаров в корзине и «любимое число» магазина. Во второй строке записаны n целых чисел p1, p2, ..., pn — цены товаров.
Формат вывода
Выведите одно целое число — минимальную сумму, которую Миша может заплатить.
Ограничения
1 ≤ n ≤ 350001 ≤ a ≤ 1 000 0001 ≤ pi ≤ 1 000 000
Пример
Ввод:
5 10
23 30 19 7 41
Вывод:
111Как решать — идея подхода
Приём: Жадный выбор по максимальной скидке
Ключевое наблюдение: купон не «пересчитывает» цену как-то сложно, он просто отбрасывает остаток при делении на a. То есть для товара с ценой p новая цена равна p - (p % a), а значит скидка на этом товаре ровно p % a.
Почему работает жадный выбор: купон можно применить только один раз, и общая сумма уменьшится ровно на скидку выбранного товара. Других эффектов (зависимости между товарами) нет, поэтому нужно просто выбрать максимальную возможную скидку.
План решения:
- Посчитай
total = sum(p[i])— сумму без купона. - Для каждого товара вычисли остаток
r = p[i] % a. - Найди
best = max(r)(если купон не применять, это эквивалентно скидке 0, ноmaxи так не меньше 0). - Ответ:
total - best.
Сложность: O(n) по времени и O(1) по памяти (кроме хранения цен, если читаешь их списком).
Частая ошибка: пытаться выбирать товар с максимальной ценой. Это неверно: важен не p, а остаток p % a (например, 100 и 101 при a=10 дают скидки 0 и 1).
Разберись руками
В корзине 5 товаров с ценами 23, 30, 19, 7, 41. Любимое число магазина — 10. Купон можно применить к одному товару и «срезать вниз» цену до ближайшего снизу кратного 10.
- Сначала посчитай сумму без купона: 23 + 30 + 19 + 7 + 41 = ?
- Теперь для каждого товара найди, сколько рублей купон СЭКОНОМИТ, если округлять цену вниз до кратной 10. Это просто «остаток при делении на 10». Заполни список экономий по порядку цен 23, 30, 19, 7, 41.
- Какой товар выгоднее всего выбрать для купона (даёт максимальную экономию)?
- Тогда минимальная сумма = сумма без купона − самая большая экономия = 120 − 9 = ?
Идея: Сначала посчитай сумму всех цен как есть. Потом для каждого товара отдельно посмотри, насколько купон уменьшит его цену при округлении вниз (это то, что «срезается»). Купон ставь на товар с самой большой экономией и вычти эту экономию из общей суммы.
Решить задачу с автопроверкой на Python →
Куда дальше
- Школьный этап ВсОШ по информатике — как устроен первый этап и план подготовки за четыре недели
- БВИ и льготы при поступлении — какой диплом что даёт и сколько лет он действует
- Перечневые олимпиады по информатике — олимпиады перечня Минобрнауки, их уровни и что нужно к диплому