Автор: | Центральная предметно-методическая комиссия | Ограничение времени: | 1 сек | |
Входной файл: | Стандартный вход | Ограничение памяти: | 512 Мб | |
Выходной файл: | Стандартный выход | |||
Максимальный балл: | 100 |
Ведётся разработка универсального банкомата, который сможет работать с любой денежной системой. Пусть в денежной системе некоторой страны используются n типов купюр, номиналы которых равны a1, a2, …, an. При этом все номиналы различны и перечислены в порядке возрастания: если i ≥ 2, то ai − 1 < ai, а также a1 = 1.
Банкомат использует следующий жадный алгоритм для выдачи купюр. Пусть клиент запросил у банкомата сумму c. Изначально есть пустой набор выдаваемых купюр. На каждом шаге алгоритм добавляет в набор купюру максимально возможного номинала так, чтобы сумма номиналов купюр в наборе не превышала c. Когда сумма номиналов купюр в наборе стала равна c, алгоритм останавливается. Отметим, что, поскольку существует купюра с номиналом a1 = 1, алгоритм всегда заканчивает работу за конечное число шагов.
Чтобы оценить эффективность данного алгоритма, требуется выяснить, какое максимальное число купюр может потребоваться выдать за один раз, если максимальная сумма, которую можно запросить, равна b. Поскольку максимальная сумма может зависеть от категории обслуживания клиента, необходимо ответить на q запросов для сумм b1, b2, …, bq.
Требуется написать программу, которая по списку номиналов купюр денежной системы и максимальной сумме, которую можно запросить, определяет сумму, которую необходимо запросить в банкомате, чтобы получить максимальное число купюр, и искомое число купюр.
Первая строка содержит целое число n — количество номиналов купюр (1 ≤ n ≤ 200 000).
Вторая строка содержит n различных целых чисел ai (1 = a1 < a2 < … < an ≤ 1018).
Третья строка содержит целое число q — количество запросов (1 ≤ q ≤ 200 000).
Следующие q строк содержат по одному целому числу bi (1 ≤ bi ≤ 1018).
Для каждого запроса выведите два числа — сумму, которую необходимо запросить в банкомате, чтобы получить максимальное число купюр, и искомое число купюр. Если существует несколько сумм, не превышающих максимального значения, для которых будет выдано максимальное число купюр, требуется вывести любую из них.
1 ≤ n ≤ 200000
1 = a1 < a2 < … < an ≤ 1018
1 ≤ q ≤ 200 000
1 ≤ bi ≤ 1018
Баллы за каждую подзадачу начисляются только в случае, если все тесты для этой подзадачи и необходимых подзадач успешно пройдены.
Подзадача | Баллы | Ограничения | Необходимые подзадачи | Информация о проверке |
---|---|---|---|---|
1 | 13 | n ≤ 500, q ≤ 5, ai ≤ 500, bi ≤ 500 | первая ошибка | |
2 | 18 | n = 60, q ≤ 5, ai = 2i − 1 | первая ошибка | |
3 | 20 | q ≤ 5, bi ≤ 2 ⋅ 105 | 1 | первая ошибка |
4 | 21 | q ≤ 5 | 1,2,3 | первая ошибка |
5 | 28 | 1,2,3,4 | первая ошибка |
№ | Стандартный вход | Стандартный выход |
---|---|---|
1 |
|
|
Рассмотрим сначала решение первых четырех подзадач, в которых q ≤ 5. В этом случае каждый запрос можно обрабатывать независимо от других, поэтому проигнорируем факт, что у нас несколько значений bi и будем решать задачу для одного значения b.
В первой подзадаче b ≤ 500, n ≤ 500, поэтому можно применить динамическое программирование. Обозначим как dp[i] количество купюр, которое будет выдано, если запросить сумму i. Тогда dp[0] = 0, и если m(i) — максимальный номинал купюры, которая не превосходит i, то dp[i] = dp[i − m(i)] + 1. Ответ — максимальное значение среди dp[1]… dp[b]. Решение работает за за O(nb).
Чтобы распространить описанное решение на третью подзадачу, избавимся от множителя n в времени работы. Для этого заметим, что m(i) только возрастает при возрастании i, поэтому в процессе вычисления dp[i] можно поддерживать текущее значение m(i) = aj и при переходе к следующему значению i проверять, нельзя ли перейти к следующему номиналу aj + 1. Время работы будет O(b + n) и третья задача решена.
Во второй подзадаче номиналы купюр являются последовательными степенями двойки. Заметим, чтобы выдать сумму c банкомат выдаст купюры с номиналами, соответствующими позициям единиц в двоичной записи числа c. Значит задача свелась к поиску числа, не превосходящего b, содержащего максимальное число единиц в двоичной записи. Пусть двоичная запись числа b содержит k разрядов. Тогда число единиц в ответе не превышает k, и число 2k − 1 − 1 заведомо меньше b и содержит ровно k − 1 двоичную единицу. Значит ответ—либо b, либо 2k − 1 − 1, получившееся решение работает за O(logb).
Решение четвертой подзадачи уже приближает нас к полному решению: ограничения на n, ai и bi в ней максимальны и только q ≤ 5. Научимся решать задачу для одного запроса b за O(n). Правильное решение основывается на жадном алгоритме.
Сделаем инверсию задачи. Пускай mnx —минимальное число c такое, что банкомат выдаст x купюр для суммы c.
Будем по-прежнему обозначать как m(v) максимальный номинал купюры, не превышающий v. Докажем, что mnx = mnx − 1 + m(mnx).
С одной стороны mnx − 1 ≤ mnx − m(mnx), поскольку из набора купюр, дающего сумму mnx, всегда можно убрать самую большую купюру (равную m(mnx)), и получим корректный набор из x − 1 купюр, дающих в сумме mnx − m(mnx). С другой стороны, предположим, что мы зафиксировали x, и mnx − 1 < mnx − m(mnx). Можно заметить, что в этом случае величина mnx − 1 + m(mnx) меньше, чем mnx, и банкомат вернет при запросе такой величины ровно x купюр — одну купюру m(mnx) (она максимальная, не превышающая этой суммы), и еще x − 1 купюр, на которые раскладывается сумма mnx − 1. Противоречие, исходное утверждение доказано.
Используя это наблюдение, можно посчитать все значения mnx за время O(n). Заметим, что для двух последовательных чисел ai, ai + 1 для всех значений x таких, что m(mnx) = ai (иными словами, самая большая купюра, если банкомат выдаёт x купюр, равна ai), значения mnx образуют арифметическую прогрессию с разностью ai и значениями в промежутке [ai;ai + 1). Посчитав такую арифметическую прогрессию для промежутка [ai;ai + 1), можно перейти к промежутку для [ai + 1;ai + 2): если последнее значение в прогрессии равно y (y < ai + 1), то следующая прогрессия начнется с y, и будет состоять из чисел y + k ⋅ ai + 1, меньших ai + 2. Чтобы найти все эти числа и их количество можно просто поделить длины соответствующих отрезков нацело на ai + 1. Таким образом, последнее число mnx, не превышающее b, и соответствующее значение x являются ответом на задачу.