Блог пользователя Malinovsky239

Автор Malinovsky239, 11 лет назад, По-русски

Добрый вечер.

При решении этой несложной задачи неожиданно столкнулся с тем, что я, кажется, не понимаю, как устроена работа функции printf. А именно есть три решения: раз, два и три.

Отличия исключительно в 47-й строке.

Почему третье решение получает WA, тогда как у двух первых ОК?

Разве функция printf не должна приводить аргумент к типу, заданному форматной строкой? А если должна, то как от приведения целочисленного нуля к double возникают проблемы?

Заранее спасибо за ответы.

Полный текст и комментарии »

  • Проголосовать: нравится
  • +21
  • Проголосовать: не нравится

Автор Malinovsky239, 12 лет назад, По-русски

A div2. Куда свернуть?

Посмотрим на векторное произведение на , численно равное . Знак векторного произведения определяется знаком синуса ориентированного угла между векторами (т.к. векторное произведение также равно ), а именно этот-то знак нам и нужно узнать.

Если произведение равно нулю, то это в данной задаче означает, что A, B и C лежат на одной прямой, а значит ответ — <>.

Если произведение больше нуля, то ответ — <>.

И, наконец, если оно меньше нуля, то ответ — <>.

Также стоит обратить внимание, что вычисление векторного произведения требуется производить в 64-битном типе, чтобы избежать переполнения.

Решение

B div2. Эффективный подход

Пусть число t стоит на позиции indt в первоначальной перестановке. Тогда, очевидно, пробегом слева направо это число будет найдено за indt сравнений, а пробегом справа налево — за n - indt + 1 сравнений. Заведем доп.массив, в i-й ячейке которого будет стоять число j такое, что aj = i. Этот массив позволит обрабатывать каждый запрос за O(1) при помощи указанных выше формул. Доп. массив строится за O(n) пробегом по массиву a. Таким образом, окончательная асимптотика решения O(n + m).

Решение

C div2 — A div1. Отсеки летающей тарелки.

Обозначим за Fn ответ на задачу, где n — число инопланетян. Давайте предположим, что мы уже решили задачу для n - 1 инопланетянина, т.е. знаем значение Fn - 1. Попытаемся найти его для n инопланетян. Заметим, что младший по рангу (далее — просто младший) инопланетянин сможет покинуть 3-й отсек только тогда, когда все остальные инопланетяне перейдут в 1-й отсек. Значит, первые Fn - 1 действий нам известны. Далее младший инопланетянин может перейти во второй отсек. Чтобы он попал в 1-й отсек, требуется, чтобы остальные вернулись в первый. Значит, требуется еще Fn - 1 действий. Наконец, после того, как младший инопланетянин перейдет в 1-й отсек требуется еще Fn - 1 действий на возвращение n - 1 инопланетянина в 1-й отсек из 3-го. Таким образом, Fn = Fn - 1 + 1 + Fn - 1 + 1 + Fn - 1. Это уже позволяет найти Fn быстрым возведением матрицы в степень, но мы пойдем чуть дальше. Прибавим по 1 к левой и правой части равенства и после элементарных преобразований получим Fn = 3·(Fn - 1 + 1) - 1. Теперь легко угадать решение рекуррентного соотношения: Fn = 3n - 1.

Осталось научиться быстро вычислять значение Fn. В этом нам поможет бинарное возведение в степень. Асимптотика решения — O(log n).

Осталось упомянуть один "подводный камень": если 3n mod m = 0, необходимо не забыть, что ответ равен m - 1, а не  - 1, и разобрать этот случай.

И напоследок маленькая аналогия: перед вами только что была задача о Ханойских башнях с модификацией, заключающейся в том, что переносы дисков разрешены только между двумя парами стержней.

Решение

D div2 — B div1. Непослушные кучки камней

Рассмотрим следующую интерпретацию задачи: кучкам камней соответствуют вершины. Операции добавить кучку a к кучке b соответствует операция подвешивания поддерева вершины b к вершине a. Числа, записанные на вершинах, — размеры кучек. Задача — добиться такой конфигурации дерева, чтобы к каждой вершине было подвешено не более k поддеревьев, а сумма произведений чисел, записанных на вершинах, на глубину вершин (где глубина корня равна 0) минимальна. Чтобы добиться минимальности, требуется, во-первых, чтобы вершина с большим числом находилась не ниже, чем вершина с меньшим (иначе их можно просто поменять и получить меньшую сумму), а во-вторых, чтобы у каждой внутренней вершины, кроме, может быть, одной было ровно k потомков (второе условие также доказывается методом от противного). Осталось научиться быстро считать для такой конфигурации саму сумму. Для этого отсортируем массив размеров кучек, а затем будем действовать так: вначале прибавим к ответу сумму размеров кучек с 1-й по k-ю (в 0-индексированном, отсортированном в порядке невозрастания массиве), домноженную на 1; затем сумму размеров следующих k^2 кучек, домноженную на 2; и т.д. до конца массива. Чтобы быстро отвечать на запрос о сумме на отрезке, предподсчитаем суммы на префиксах сразу после того, как отсортируем массив. Теперь при k > 1 мы умеем находить ответ на запрос за O(log n). Если тем же соображениям следовать при k = 1, ответ на запрос будет занимать O(n) операций, а потому решение получит TL, если в большей части запросов k будет равно 1. Поэтому следует заранее посчитать ответ для k = 1 и запомнить его, чтобы отвечать на такие запросы за O(1).

Асимптотика решения — O(n · log n  +  q · log n).

Решение

E div2 — C div1. Юбилей

Сначала докажем ключевое утверждение: НОД(Fn, Fm) = FНОД(n, m).

Начнем издалека: выразим Fn + k через Fn и Fk. Получим следующую формулу: Fn + k = Fk·Fn + 1 + Fk - 1·Fn. Эта формула доказывается по индукции.

Теперь воспользуемся полученной формулой и заметим, что НОД(Fn + k, Fn) = НОД(Fk, Fn).

Осталось заметить в последней формулой аналогию с алгоритмом Евклида и осознать, что мы получили требуемое нам соотношение для НОД двух чисел Фибоначчи.

Итак, мы свели задачу к следующей: найти в заданном множестве подмножество из k (или хотя бы из k) элементов с максимально возможным НОД. А точнее, найти сам НОД такого подмножества.

Пусть ответ равен q. Тогда должно выполняться  -  ⌉ + 1 ≥ k (1).

Заметим, что для каждого из слагаемых из левой части неравенства существует отрезков, на которых его значение постоянно. Причем мы можем найти все эти отрезки и значения за . Точнее, нас интересуют такие q, что в q - 1 значение хотя бы одного из слагаемых меняется (очевидно, увеличивается). Таких значений тоже . Осталось перебрать их все и каждое попробовать в роли ответа (т.е., для каждого проверить неравенство (1)), а из подошедших выбрать максимум. Ответ всегда будет, т.к. единица подходит на роль q при любых входных данных.

Таким образом, мы нашли индекс искомого числа Фибоначчи. Само же число можно вычислить, быстро возведя матрицу в степень.

Решение

Асимптотика решения — .

D div1. Всего лишь таблица.

Научимся получать ответ. Поступим следующим образом: будем находить любую строку или столбец с отрицательной суммой и инвертировать его/ее. Заметим, что сумма всех чисел в таблице после таких операций неизменно будет возрастать. Очевидно, что возрастать бесконечно сумма не может. За один шаг сумма возрастает хотя бы на 2, а максимальное возможное изменение суммы относительно начальной — 200·n·m. Таким образом, всего потребуется не более 100·n·m операций (применения заклинания), каждая из которых выполняется за время O(n) или O(m). Итак, мы научились получать нужную таблицу за ~ 1004 действий.

Осталось восстановить ответ. Легко понять, что в него войдут те строки и столбцы, которые мы инвертировали нечётное число раз.

Решение

E div1. Путь благородного рыцаря

Решение 1

Нетрудно догадаться, что замки образуют дерево. Построим на этом дереве heavy-light decomposition. Над каждым путем построим персистентное дерево отрезков на сумму. В вершине дерева отрезков будет храниться 0, если замок на текущий момент не тронут варварами, и 1 в противном случае.

Каждый путь рыцаря можно при помощи нахождения lca разбить на не более чем два подпути, лежащие на пути от одного из концов маршрута к корню. Теперь будем решать задачу для каждого из подпутей отдельно. Будем последовательно обрабатывать пути из heavy-light decomposition и одиночные вершины, принадлежащие подпути. Нас интересует количество вершин на подпути, которые не посещались с года y + 1 по текущий, т.е. (в случае пути из декомпозиции) таких, что разность между значениями в текущей версии персистентного дерева и в версии, соответствующей году y (требуемая версия ищется бинпоиском в списке версий) равна нулю (случай с одиночной вершиной тривиальнее: достаточно просто хранить время посещения вершины). Как только количество подходящих вершин станет не меньше k, нам останется синхронно спуститься по двум версиям дерева, чтобы получить ответ.

Если на первом подпути k-я вершина не найдена, то следует обратить внимание, что поскольку мы идем по дереву всегда снизу вверх, то надо аккуратно пересчитать номер вершины, чтобы узнать, какой она должна быть по счету на втором подпути, считая снизу вверх.

Асимптотика решения: O(m·log2 n) — в каждом запросе первого типа нам может потребоваться обновить какое-нибудь дерево отрезков, на что уйдет O(log n) операций; в каждом запросе второго типа нам встречается O(log n) путей декомпозиции, каждый из которых обрабатывается за O(log n) (вначале бинпоиск по версиям, затем запрос к дереву/спуск по дереву).

Реализация

Решение 2

Обойдем дерево dfs'ом, записывая в массив номер вершины в моменты входа и выхода (аналогия с правильными скобочными последовательностями). Причем как записи о входе, так и записи о выходе сопоставим 0. На этом массиве построим персистентное дерево отрезков.

Теперь, когда нам будет поступать запрос первого типа, будем сопоставлять позиции первого вхождения вершины в массив  + 1, а позиции последнего вхождения —  - 1.

Для того чтобы научиться обрабатывать второй запрос, заметим, что для нахождения количества посещенных вершин на произвольном подпути между вершинами a и b такими, что обе вершина a лежит на пути от вершины b до корня, нам требуется найти сумму чисел, сопоставленных позициям между первыми вхождениями вершин в созданном обходом в глубину массиве.

Теперь на каждом из подпутей в отдельности запустим двоичный поиск по ответу — позиции искомого замка. Для проверки ответа воспользуемся приведенным в предыдущем абзаце соображением.

Асимптотика решения: O(m·log2 n) — в каждом запросе первого типа нам может потребоваться обновить дерево отрезков, на что уйдет O(log n) операций; в каждом запросе второго типа O(log n) итераций бинпоиска по ответу, каждая из которых обрабатывается за O(log n).

Реализация

upd. Исправил маленькую неточность в неравенстве в разборе E div2 — C div1. В левой части добавился +1.

Полный текст и комментарии »

Разбор задач Codeforces Round 140 (Div. 1)
  • Проголосовать: нравится
  • +57
  • Проголосовать: не нравится

Автор Malinovsky239, 12 лет назад, По-русски

Всем привет!

Сегодня в 19:30 по Московскому времени состоится 140-й раунд Codeforces. Соревнование пройдет в обоих дивизионах.

Автором задач сегодняшнего раунда являюсь я, Илья Малиновский, студент 1-го курса мат-меха СПбГУ. Это мой первый контест на Codeforces.

Хочется поблагодарить Геральда Агапова (Gerald) за колоссальную помощь в подготовке раунда, Марию Белову (Delinur) за перевод условий на английский язык и Михаила Мирзаянова (MikeMirzayanov) за саму возможность готовить контесты (а также в них участвовать) на базе Codeforces.

Участникам предстоит традиционно выступить в роли спасителей всех и вся от разнообразных бед и невзгод. У вас будет два часа на то, чтобы помочь былинному богатырю, инопланетянину, благородному рыцарю и другим персонажам. Кроме того, в одной из задач найдется место и антагонистам: в их роли выступят коварные кучки камней...

Надеюсь, что задачи понравятся всем участникам (зачем хотеть того, чего не бывает) подавляющему большинству участников.

Успехов!

P.S. Информация о разбалловке появится незадолго до начала раунда.

upd. Разбалловка стандартная в обоих дивизионах.

upd 2 Раунд завершён!

Поздравляем победителей!

div1:

  1. peter50216

  2. Dmitry_Egorov

  3. Egor

  4. RAVEman

  5. bmerry

У победителей по 3-4 задачи. Задача E не покорилась ни одному участнику.

div2:

  1. Velicue (он единственный в дивизионе сдал все 5 задач)

  2. Frommi

  3. Aerolight

  4. Shahriar_sust

  5. bzdbz

Всем спасибо за участие! Надеюсь, в целом все понравилось. До новых встреч!

P.S. Разбор будет опубликован завтра вечером.

Полный разбор

Полный текст и комментарии »

  • Проголосовать: нравится
  • +235
  • Проголосовать: не нравится

Автор Malinovsky239, 12 лет назад, По-русски

Добрый вечер!

Сегодня с 18:00 до 21:00 по Москве проходил 5-й раунд хорватских интернет-олимпиад сезона 2011/2012. Предлагается обсудить здесь задачи.

И сразу несколько вопросов к тем, кто писал:

1) Как решать 5-ю? Интересуют как идеи частичных решений, так и, разумеется, полного.

2) Как решать 6-ю на полный балл?

3) Как понимать "_warning: the `gets' function is dangerous and should not be used_"? Первый раз сталкиваюсь с подобным. По каким причинам функция gets() объявлена вне закона?

Полный текст и комментарии »

  • Проголосовать: нравится
  • +19
  • Проголосовать: не нравится

Автор Malinovsky239, 12 лет назад, По-русски

Некоторое время назад (если не ошибаюсь, позавчера) перестал быть доступен сайт acm.timus.ru, причём не только по вышеуказанному адресу, но и по acm-judge.usu.ru. Кто-нибудь знает, когда следует ожидать восстановления работоспособности системы?

Полный текст и комментарии »

  • Проголосовать: нравится
  • +23
  • Проголосовать: не нравится

Автор Malinovsky239, 13 лет назад, По-русски

Во время контеста зашёл во вкладку "Результаты друзей". Первые 20 человек отображались без проблем. Но в раунде участвовало 27 человек, добавленных мной в друзья. При щелчке на надпись "21-27" под таблицей меня перекидывало в общую таблицу на 21-40 места (а насколько я понимаю, должно было на 21-27 места среди моих друзей). Это связано с ограничением функциональности системы во время раунда? Или с чем-то другим?


P.S. Заранее извиняюсь, если я что-то неправильно понял, и всё работало, как должно было.

Полный текст и комментарии »

  • Проголосовать: нравится
  • +10
  • Проголосовать: не нравится

Автор Malinovsky239, 13 лет назад, По-русски
Очень хотелось бы иметь возможность переходить по ссылке из контеста в режиме дорешивания в пост с разбором задач соответствующего раунда: я считаю, что так будет значительно удобнее тем людям, кто, например, сейчас решит потренироваться на задачах самых первых CF Beta Round'ах.

Полный текст и комментарии »

  • Проголосовать: нравится
  • +10
  • Проголосовать: не нравится

Автор Malinovsky239, 13 лет назад, По-русски
Объясните, пожалуйста, принцип подсчёта рейтинга участника соревнований Codeforces.

Полный текст и комментарии »

  • Проголосовать: нравится
  • -1
  • Проголосовать: не нравится