Разбор задач III этапа республиканской олимпиады по учебному предмету "Информатика" 2018/2019
←
→
Транскрипция содержимого страницы
Если ваш браузер не отображает страницу правильно, пожалуйста, читайте содержимое страницы ниже
Разбор задач III этапа республиканской олимпиады по учебному предмету “Информатика” 2018/2019 Коробейников Ф.А. Заржицкий И.А. Мелех А.А. Клещёв М.И. Козловский А.С. Керножицкий А.С.
Условие Дана последовательность 1, 1, 2, 1, 2, 3, 1, 2, 3, 4, ... Найти сумму на отрезке [L, R].
ГРУППЫ ТЕСТОВ Баллы 70 L ≤ R ≤ 106 90 R - L ≤ 106
70 баллов, L ≤ R ≤ 106 ● Пройдём по последовательности, считая сумму.
90 баллов, L - R ≤ 106 ● Разобьем последовательность на группы. 1, 1, 2, 1, 2, 3, 1, 2, 3, 4, … ● Заметим, что размеры групп составляют арифметическую прогрессию. ● Тогда по номеру числа из формулы суммы арифметической прогрессии (n ∗(n+1))/2 можно найти группу, в которой находится это число, а также границы этой группы. ● Зная, к какой группе принадлежит L и какое число под этим номером, можем просто пройтись по последовательности до R.
Полное решение ● Так же как и 90 баллов, только заметим, что мы можем сразу считать сумму целой группы, так как это тоже арифметическая прогрессия. ● Посчитаем сумму всех групп между группами L и R и аккуратно посчитаем суммы самих групп, L и R. ● Итоговая асимптотика примерно O(√R)
II. Дружелюбные соседи Количество решений 41 Средний балл по задаче 49.07 Количество полных решений 0
Условие Дано N комнат, пронумерованных целыми числами от 1 до N по часовой стрелке, причем i-я комната граничит с i+1, n-ая с 1 В каждой комнате живет ровно один марсианин, причем у каждого есть коэффициент его дружелюбности Ai Два марсианина с дружелюбностью X и Y соответственно враждуют, если X & Y ≠ 0 Требуется разделить дом на как можно меньшее число квартир так, чтобы никакие два марсианина в одной квартире не враждовали
ГРУППЫ ТЕСТОВ Баллы N, Ai 20 N ≤ 50, Ai ≤ 2 40 N ≤ 50, Ai - степени двойки 60 N ≤ 50, Ai ≤ 109 80 N ≤ 300, Ai ≤ 109 90 N ≤ 2000, Ai ≤ 109
20 баллов, N ≤ 50, Ai ≤ 2 ● Заметим, что может быть всего 4 варианта квартир: [1, 2] [2, 1] [1] [2] ● Для того, чтобы минимизировать ответ, нужно максимизировать количество [1, 2] [2, 1] ● Запустим перебор из каждой комнаты и жадно добираем до нужного нам блока
40 баллов, N ≤ 50, Ai - степени двойки ● Заметим, что в квартире не будет враждующих жителей, если в ней все Ai различные ● Для этого запустим перебор из каждой комнаты и будем набирать жадно, пока в квартире различные Ai, поддерживая минимальный ответ
60 баллов, N ≤ 50, Ai ≤ 109 ● Запускаем жадный алгоритм из каждой комнаты ● При добавлении марсианина в квартиру, проверяем, что все жильцы не враждуют друг с другом ● Итоговая асимптотика: O(N4)
80 баллов, N ≤ 300, Ai ≤ 109 ● Запускаем жадный алгоритм из каждой комнаты ● При добавлении марсианина в квартиру, проверяем, что применение операции & к его дружелюбности с дружелюбностью уже набранных жителей даёт 0 ● Итоговая асимптотика O(N3)
90 баллов, N ≤ 2000, Ai ≤ 109 ● Запустим жадный алгоритм из каждой комнаты, добирая новых жильцов до тех пор, пока они не враждуют с уже живущими ● Итоговая асимптотика: O(N2)
ПОЛНОЕ РЕШЕНИЕ ● Для того, чтобы решить эту задачу, нужно было заметить, что никакая квартира не может состоять из более чем 30 марсиан ● Если в квартире оказалось больше чем 30 марсиан, то по принципу Дирихле найдется хотя бы 1 пара марсиан, которая будет враждовать(109 ≈230) ● Возьмем любые 30 подряд идущих комнат, можно сказать, что среди этих комнат точно найдется начало квартиры в минимальном разбиении на квартиры
ПОЛНОЕ РЕШЕНИЕ ● Возьмем любые 30 подряд идущих квартир и запустим жадный алгоритм, пока все жильцы не будут враждовать друг с другом, параллельно поддерживая минимум ● Итоговая асимптотика О(30*N)
III. Поворот плиток Количество решений 13 Средний балл по задаче 13.69 Количество полных решений 0
Условие Дана NxM матрица из плиток На некоторых из плиток находится две диагональные дороги Необходимо повернуть не более K плиток таким образом, чтобы количество путей было минимально. Виды плиток:
ГРУППЫ ТЕСТОВ Баллы N, M, K 20 N, M ≤ 10, K = 1 40 N, M ≤ 10, K ≤ 2 60 N, M, K ≤ 50 80 N, M, K ≤ 300 100 N, M ≤ 1000, K ≤ 109
40 баллов, N,M ≤ 10, K ≤ 2 ● Имеем K ≤ 2 ● Можно перебрать одну или две плитки, которые необходимо повернуть ● После этого можно найти количество дорог с помощью, например, поиска в глубину или в ширину
60 баллов, N,M,K ≤ 50 ● Воспользуемся жадным алгоритмом ● Выбираем плитку, после поворота которой количество путей станет минимально возможным ● Повернем эту плитку, если это не ухудшит ответ ● Повторим описанную выше операцию K раз ● Корректность этого решения будет видна, исходя из полного решения
Дополнительные наблюдения ● Всего существует два типа путей – циклы и цепочки ● Через одну клетку проходит не более двух путей ● Рассмотрим различные случаи прохождения путей через некоторую плитку до и после поворота
Улучшенное решение Таким образом, существует всего пять вариантов изменения путей после поворота одной плитки. Из этих вариантов только два позволяют уменьшить количество циклов: объединение двух циклов и объединение цикла и цепочки. Подход к решению состоит в том, что нам надо искать первые K плиток, позволяющих выполнить уменьшение числа циклов. Пусть количество найденных плиток равно t, а количество улиц на изначальном плане Олимп-Сити равно p. Ответ в этом случае равен p – t. В зависимости от реализации это решение может набрать различное (но неполное) количество баллов.
Полное решение Рассмотрим начальное состояние карты и рассчитаем количество цепочек и циклов. Обозначим эти величины через L и C соответственно. Отметим следующие факты: • при повороте любой плитки количество цепочек не изменяется; • при повороте одной плитки количество циклов можно уменьшить не более чем на 1; • для любого цикла найдётся хотя бы одна клетка, в которой он соседствует с другим циклом или цепочкой. Следовательно, количество циклов можно уменьшить на K, либо избавиться от них вообще. Ответом будет величина L + max(0, C-K).
IV. Садовник Количество решений 58 Средний балл по задаче 1.51 Количество полных решений 0
Условие Дана последовательность из N целых чисел Z1, Z2, …, Zn. Даны q запросов. Запросы бывают 2 типов: 1. X. Заменить все вхождения X в последовательности на X + 1. 2. L R K. Посчитать количество i таких, что Zi < K
ГРУППЫ ТЕСТОВ Баллы N, Q, Zi 30 N, Q ≤ 100 000, Zi ≤ 50 60 N, Q ≤ 100 000, Zi ≤ 200 90 N, Q ≤ 200 000, Zi ≤ 100 000 100 N, Q ≤ 500 000, Zi ≤ 1 000 000
30-60 баллов, N,Q ≤ 100 000, Zi ≤ 200 ● Заметим, что после запроса первого типа количество различных чисел в последовательности Z может либо остаться таким же, либо уменьшиться на один. ● Обозначим за tox - число, в которое перейдет x после текущих запросов. ● Тогда, используя tox можно ответить на запрос за количество различных чисел в последовательности Z. т.е. запросы второго вида мы свели к такому типу запросов: узнать количество чисел равных K на отрезке [L, R]. Сделать это можно с помощью бинарного поиска (30 баллов) или префиксных сумм (60 баллов).
Ключевое наблюдение ● tox≤ tox+1. Тогда запрос второго типа сводится к запросу: узнать количество чисел на отрезке L R, которые меньше какого-то W ● Как узнать W? Используя монотонность tox, W можно найти бинарным поиском (т.е. нам надо найти такое наибольшее x, такое, что tox < K)
90 баллов, N,Q ≤ 200 000, Zi ≤ 100 000 ● Построим дерево отрезков, в котором в каждой вершине будет храниться список отсортированных Z из отрезка, который соответствует этой вершине. Тогда на запрос можно отвечать за log2(N). ● Итоговая сложность O(N log(N) + Q log 2(N)).
Полное решение ● Заметим, что на запросы можно отвечать offline. Используем метод событий. События бывают 2 видов: 1. i K. активировать число на позиции i 2. L R K. узнать количество активированных чисел на отрезке [L, R]. Здесь для каждого запроса мы должны получить его актуальное значение K (как мы описывали W ранее) Понятно, что события второго типа - это запросы второго вида, а события первого типа - это все пары {i, Zi}. События сортируются по K и обрабатывать их можно с помощью дерева отрезков или дерева Фенвика. Итоговая сложность O(N log(N) + Q log(N)).
ЗАДАЧИ ВТОРОГО ДНЯ
I. Доставка Количество решений 59 Средний балл по задаче 87.5 Количество полных решений 13
Условие Дана матрица NxM, K клеток, которые нужно посетить, начальная позиция почтальона X, Y Требуется найти количество клеток, которые может посетить почтальон, при условии, что он может двигаться по диагонали
ГРУППЫ ТЕСТОВ Баллы N, M 30 N, M ≤ 3 70 N, M ≤ 10
30 баллов, N, M ≤ 3 Рассматриваем все варианты расположения клеток и пишем if на каждый случай
70 баллов, N, M ≤ 10 Запускаем поиск в глубину без запоминания посещения (тем самым некоторые дома могут быть посещены многократно, что на больших тестах приведёт к превышению лимита времени)
100 баллов, N, M ≤ 1000 почтальон сможет посетить клетку (x, y), если (x+y) и (X0+Y0) имеют одинаковую чётность отдельно нужно рассмотреть случаи 1xN и Nx1, так как почтальон не сможет двигаться. В этом случае он сможет посетить единственный дом, находящийся по адресу (X0, Y0). К сожалению, многие участники упустили из виду этот крайний случай и получили 96 баллов из 100
II. Контрольная работа Количество решений 36 Средний балл по задаче 17 Количество полных решений 0
Условие Дано 3 целых числа N, M, K Требуется найти количество последовательностей из N целых чисел каждое от 1 до K, так что их произведение делится на M.
ГРУППЫ ТЕСТОВ Баллы N, M, K 20 N ≤ 100, M = K = 2 40 N ≤ 5000, M, K ≤ 3 60 N, M, K ≤ 500 80 N, M, K ≤ 2000 100 N, M, K ≤ 10000
20 баллов, N ≤ 100, M = K = 2 Последовательность должна состоять из чисел 1 и 2 Произведение будет кратно 2 только в том случае, если хотя бы одно из чисел – двойка Ответ равен 2^N - 1
40 баллов, N ≤ 100, M,K ≤ 3 Здесь необходимо рассмотреть различные случаи Случай M = 2, K = 2 рассмотрен ранее В случае M = 3, K = 3 необходимо, чтобы хотя бы одно из чисел было равно 3, поэтому ответ равен 3^N-2^N Оставшиеся случаи рассматриваются аналогично
60 баллов, N, M, K ≤ 500 Воспользуемся методом динамического программирования dp[i][j] – количество способов выбрать последовательность из i чисел так, чтобы остаток от деления на M был равен j Начальное состояние – dp[0][1] = 0, ответ находится в dp[N][0] Пересчет динамики: for i in 1..N for j in 0..M-1 for k in 1..K dp[i+1][(j*k) mod M] += dp[i][j] Итоговая сложность решения – O(N*M*K)
80 баллов, N, M, K ≤ 2000 Вместо j (остатка от деления на M) рассмотрим НОД(j, M) Таким образом, второе измерение динамики dp[i][j] будет иметь меньшее число вариантов Нетрудно видеть, что НОД(j, M) является делителем M, поэтому число различных j равно числу делителей Таким образом, мы можем считать динамику за O(N*D*K), где D – количество делителей (порядка 60 в худшем случае)
100 баллов, N, M, K ≤ 10000 Осталось избавиться от K в асимптотике Для этого посчитаем массив go[i][j] – количество способов выбрать число k от 1 до K так, чтобы НОД(i*k, M) =j С помощью перебора чисел i и k такой массив можно подсчитать за O(K*D) Используя go[i][j], нетрудно улучшить асимптотику до O(N*D^2)
III. Текстовый редактор Количество решений 57 Средний балл по задаче 37 Количество полных решений 2
Условие Дано N строк. Назовём непохожестью строк А и В величину, равную минимальному количеству действий, необходимых для того, чтобы получить из строки A строку B. Действия: 1) удалить последний символ в строке 2) приписать любой символ справа в строку. Необходимо найти сумму непохожести по всем парам строк.
ГРУППЫ ТЕСТОВ Баллы N 40 N ≤ 100 60 N ≤ 5000
40 баллов, N ≤ 100 Обозначим через S сумму длин всех строк Перебираем все пары строк и посимвольно ищем наибольший общий префикс Итоговая асимптотика: О(N*S)
60 баллов, N ≤ 5000 Воспользуемся идеей на 40 баллов, но искать общий префикс будем с помощью хеш-функции Итоговая асимптотика: O(N2*log2S)
Полное решение Строим на строках бор (описание этой структуры данных, можно посмотреть, например, здесь: https://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BE%D1%80) Считаем для каждой вершины бора количество символов ниже текущей вершины, учитывая повторения (массив Dp) и вес ребра бора (массив V).
Полное решение Запускаем механизм динамического програмирования со следующими переходами: Если мы пришли в вершину i, которая является концом k строк, то прибавляем к ответу Dp[i] * k Если из вершины i есть переход в более чем одну вершину(допустим, в вершины a и b), то прибавляем к ответу (Dp[i] - Dp[a] - V[i][a]) * V[i][a] и переходим в вершину a. Если вершина является листом, то возвращаемся назад. Заметим, что для полного ответа надо полученный ответ умножить на два, чтобы учесть, что d(A, B) = d(B, A). Итоговая асимптотика: O(S)
IV. Послание инопланетянам Количество решений 55 Средний балл по задаче 33 Количество полных решений 1
Наименьшая общая надстрока Нетрудно заметить, что условие задачи является практически незавуалированной формулировкой известной задачи о наименьшей общей надстроке (minimum superstring problem). Данная задача имеет большое прикладное значение, в частности, в медицине и биологии для секвенирования ДНК. К сожалению, данная задача является NP-трудной. В простых терминах это означает, что оптимального решения с полиномиальной сложностью для нее скорее всего не существует. Поэтому от участников олимпиады ожидаются экспоненциальные решения (переборы) с различными отсечениями. Стоит отметить, что значительная часть тестов содержит небольшое число строк (менее 15), что позволяет найти оптимальное решение за разумное время (до десятков минут) в ходе соревнования. Некоторые тесты можно решить вручную.
Полное решение (один из подходов) Вначале нужно удалить строки, которые являются подстроками других строк. Затем обозначим через f[i][j] такое наибольшее k, что суффикс длины k i-ой строки равен префиксу длины k j- ой строки. Затем можно воспользоваться методом динамического программирования. dp[i][mask], где mask - маска тех, кого уже включили в ответ, а i – строка, которую добавили последней, тогда если мы хотим добавить строку с номером j, то переход будет таким: dp[j][mask + 2 j] = max(dp[j][mask + 2j], dp[i][mask] + length(sj) - f[i][j]). Итоговая сложность: 2N * N2
Вы также можете почитать