Динамика, жадные алгоритмы и сортировка (задания 23, 26, 27)
Подсчёт программ исполнителя, жадный выбор интервалов и файлов, префиксные суммы и остатки, линейные алгоритмы вместо перебора.
Динамическое программирование (задание 23)
В задании 23 исполнитель имеет несколько команд (+1, +2, ×2 …); нужно найти число программ, переводящих a в b, часто с обязательной точкой и запрещённой точкой. Если d[n] — количество программ, приводящих к числу n, то d[n] равно сумме d[m] по всем числам m, из которых за одну команду можно получить n. Путь через обязательную точку c — это произведение d(a→c)·d(c→b); запрещённая точка просто обнуляется (d[x] = 0).
ПримерПрограммы с командами +1 и ×2
ПримерЛестница с шагами 1, 2 и 3
Жадные алгоритмы и сортировка (задание 26)
Жадный алгоритм на каждом шаге выбирает локально лучший вариант. В задании 26 это почти всегда «отсортировать данные по подходящему ключу и пройти один раз». Ключ сортировки определяет правильность: для набора максимального числа непересекающихся интервалов нужно сортировать по времени окончания, для максимального числа файлов на диске — по размеру по возрастанию.
ПримерМаксимум непересекающихся интервалов
ПримерФайлы на диске
Префиксные суммы и остатки (задание 27)
Для файлов до 10⁷ чисел нужен один проход. Если pref[k] — сумма первых k элементов, то сумма фрагмента (i, j] равна pref[j] − pref[i]. Условие «сумма делится на m» означает pref[i] ≡ pref[j] (mod m): достаточно хранить, сколько раз встретился каждый остаток (для подсчёта числа фрагментов) или где он встретился впервые (для самого длинного фрагмента). Для пар элементов с условием на сумму или разность хранят минимумы и максимумы по остаткам.