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

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

Только что закончился очередной opencup. Давайте обсуждать задачи здесь :)

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

»
9 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Расскажите, пожалуйста, как решались задачи G, C и D?

  • »
    »
    9 лет назад, # ^ |
      Проголосовать: нравится +1 Проголосовать: не нравится

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

    • »
      »
      »
      9 лет назад, # ^ |
        Проголосовать: нравится +6 Проголосовать: не нравится

      Не забыв отдельно разобрать случай когда n = 1 или m = 1. Иначе WA20.

  • »
    »
    9 лет назад, # ^ |
      Проголосовать: нравится +13 Проголосовать: не нравится

    D: Пусть k=1. Посчитаем для строки s динамику dp[i][mask] — количество упорядоченных наборов из n чисел из i бит каждое, где j-ый бит mask (j=0..n-1) равен 1, если j-ое число строго больше (j+1)-го, и равен 0, если эти числа равны (числа нумеруем от 1 до n, нулевое число это само s). В начале dp[0][0] = 1, в конце ответ хранится в dp[|s|][2^n-1] (все числа различны и максимальное из них строго меньше s), переходы делаются перебором набора i-ых битов.

    Заметим, что точно такую же динамику можно считать, беря начальным значением dp[0][mask] = 1 для любой маски mask, давайте за a[mask1][mask2] обозначим dp[|s|][mask2], когда за начальное значение взято dp[0][mask1] = 1.

    Теперь заметим, что для k=2 можно просто перебрать "маску равенств" после первых |s| бит, т.е. ответ для k=2 это сумма a[0][z] * a[z][2^n — 1] по всем маскам z. Заметим, что если считать, что a — матрица, то ответ для k=2 — это элемент с тем же самым индексом, что при k=1, но не матрицы a, а матрицы a^2. Точно так же ответ для произвольного k хранится в том же самом месте в матрице a^k. Осталось воспользоваться бинарным возведением матрицы в степень.

  • »
    »
    9 лет назад, # ^ |
    Rev. 3   Проголосовать: нравится +5 Проголосовать: не нравится

    Ещё одно решение D за другую сложность. Забудем, что числа должны быть различными. Тогда ответ можно насчитать такой динамикой: dpij — ответ для i-ого префикса, если j чисел из набора уже меньше, чем R, а остальные равны R. С помощью той же идеи, что описал Copymaster, можно посчитать её за O(n3 * (|s| + log(k)). Теперь нужно посчитать все множества, в которых есть различные числа. Для этого перебираем все разбиения на подмножества, для каждого разбиения считаем, сколько подмножеств чётного размера, а сколько — нечётного. Пусть чётных множеств x, а нечётных множеств — y. Тогда количество способов выбрать n чисел, так чтобы все числа в одном множестве были равны, а в разных — различны, равно ansx * (r - x) * (r - x - 1) * ... * (r - x - y + 1), где ansx — количество множеств размера x без одинаковых элементов. Итоговая сложность — O(n4 * (|s| + log(k)) + n2 * Bn), где Bnn-ое число Белла.

    • »
      »
      »
      9 лет назад, # ^ |
      Rev. 3   Проголосовать: нравится +8 Проголосовать: не нравится

      Понятно, что от числа Белла можно избавиться. Достаточно считать количество сколько разбиейний множества из n элементов на k четных и l нечетных. Это делается кубической динамикой.

      Так как надо посчитать для всех n ответы, то нужно n4 * ...

»
9 лет назад, # |
  Проголосовать: нравится +8 Проголосовать: не нравится

Интересно узнать, как решалась I. Видимо, промоделировать последние 10^7 шагов — неверно?)

  • »
    »
    9 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Хватило промоделировать последние 8к шагов влоб

  • »
    »
    9 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Рассмотрим любую клетку после первых 4к шагов — теперь у нас за один шаг покрывается целый столбец или целая строка, так вот если покрывается столбец или строка, то в следующий раз он покроется не больше чем через 4к шагов — это можно доказать из того, как смещаются покрываемые столбцы и строчки относительно начальной позиции — для столбцов (0, +2, -2, +4), для строк (-1, 2, -3, 4) — такая последовательность задает равномерное покрытие

    • »
      »
      »
      9 лет назад, # ^ |
        Проголосовать: нравится +8 Проголосовать: не нравится

      Всё понятно, только откуда следует, что покрытие равномерное?)

      • »
        »
        »
        »
        9 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится

        Вот — я пока писал комент выше — понял еще одну интересную вещь рассмотрим процесс когда уже stepsize >= m, теперь всякое покрытие строчки будет покрывать ее всю

        как я уже выше писал — последовательность, которая задает номера строчек для покрытия — (-1, 2, -3, 4, -5), через n/2 шагов нечетные элементы последовательности покроют все нечетные строки, четные элементы последовательности покроют все четные строки

»
9 лет назад, # |
  Проголосовать: нравится +13 Проголосовать: не нравится

У кого-нибудь в F зашёл поток в даблах на джаве? По слухам в интах заходил, но я пихал в даблах, и не утолкался ни Диниц, ни preflow push, ни разнообразные оптимизации...

  • »
    »
    9 лет назад, # ^ |
      Проголосовать: нравится +8 Проголосовать: не нравится

    У нас зашел. Такой код на Яндекс.Контесте работает 442мс.

    • »
      »
      »
      9 лет назад, # ^ |
        Проголосовать: нравится +11 Проголосовать: не нравится

      Спасибо за код! Удивительно, что это работает безо всяких epsilon'ов (даже сравнение capacity и flow в конце точное!)

      Что самое интересное, избавление от epsilon'ов в моём коде тоже даёт AC, 462ms для Диница. Учитывая, что с epsilon'ами тот же самый код получал ТЛ (>4c) — сравнение не с нулём тормозит программу в ~10 раз. Это довольно удивительно, единственное, что я могу предположить, — JIT сходит с ума, когда видит сравнение с числами вроде 1E-9. Но если подобный эффект наблюдается и для C++-программ, то тут что-то совсем весёлое.

      • »
        »
        »
        »
        9 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится

        А можешь попробовать в коде с епсами сделать так, чтобы в ребра, которые меньше eps сразу записывался 0?

»
9 лет назад, # |
Rev. 5   Проголосовать: нравится +21 Проголосовать: не нравится

Может кто нибудь покритиковать такое решение А:

Ясно, что если есть какая-то окружность, являющаяся ответом, то есть и такая, которая касается каких-то двух миньонов. (Ну или ответ — единица). Переберем эту пару. Таким образом мы задали семейство окружностей с центром на серединном перпендикуляре отрезка (между этими двумя миньонами). Бинпоиском найдем наибольший возможный радиус окружности (и центр, соответственно, тоже), и посмотрим, сколько миньонов внутри. Возьмем максимум.

Работает вроде как О (m^2*nLog(MAXR) + m^3) = O (m^3), где MAXR — ограничение на радиус. За 10 секунд можно и упихать наверно :)

  • »
    »
    9 лет назад, # ^ |
      Проголосовать: нравится +29 Проголосовать: не нравится

    Дай знать, если зайдет в дорешку =)

    • »
      »
      »
      9 лет назад, # ^ |
      Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

      Кто-то дорешал уже? Расскажите :)

      У меня похожее решение за куб уперлось в WA52. Ни у кого случайно не было? :) Догадываюсь, что мне в некоторых случаях не хватает точности.

»
9 лет назад, # |
  Проголосовать: нравится -18 Проголосовать: не нравится

Привет. Реквестую Е, Н див2.

  • »
    »
    9 лет назад, # ^ |
      Проголосовать: нравится +18 Проголосовать: не нравится

    H: Проведём рёбра от i к f(i). Для каждого снека выберем одно входящее ребро, с помощью которого можно получить выгоду (если их несколько — наибольшую). Пока все снеки есть хотя бы по одному, набираем. Потом может возникнуть проблема — граф с выбранными рёбрами может образовывать цикл, и взять все снеки, используя эти рёбра, не получится. Тогда постараемся минимизировать убыток в этом цикле. Рассмотрим каждый снек, прибылью которого мы жертвуем. Мы можем либо не взять его совсем, либо взять с помощью другого менее выгодного ребра, ведущего к нему, не входящего в цикл, если такое существует. Прибавляем к ответу прибыль по всему циклу, минимальный убыток отнимаем. В цепочках проблем нет, просто прибавляем суммарную прибыль от них.

  • »
    »
    9 лет назад, # ^ |
      Проголосовать: нравится +5 Проголосовать: не нравится

    E — будем искать ответ бинпоиском. Понятно, что верхняя граница — это минимальное среди значений по всем возможным группам из одного числа.

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

»
9 лет назад, # |
  Проголосовать: нравится +9 Проголосовать: не нравится

Расскажите еще G пожалуйста. Я пробовал упихать перебор, но дальше 38 теста дойти не удалось

  • »
    »
    9 лет назад, # ^ |
    Rev. 2   Проголосовать: нравится -8 Проголосовать: не нравится

    1) Перебираем все возможные строки-кандидаты на ответ. Их мало (совсем верхняя граница говорит 18*200, но если рассматривать лишь различные, и смотреть на число символов, их будет мало)

    2) Пишем динамику за n^3 / len: dp[i][j]=можно ли получить из пустой строки подстроку с i по j. Переход с помощью вспомогательной динамики dp2[j]: можно ли при фиксированном i получить строку i..j (считаем, что (j-i-1) % len + 1 символов относятся к самой "первой", внешней, строке, из которой получаем i..j).

    Заходит за 50 мс.

    • »
      »
      »
      9 лет назад, # ^ |
        Проголосовать: нравится -8 Проголосовать: не нравится

      Не очень понятно, что делает вторая динамика и соответственно как делается переход в первой. Если не сложно, скиньте еще пожалуйста код.

      • »
        »
        »
        »
        9 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится

        Как-то так. В main'e перебирается подстрока-ответ, а в solve проверяется, подходит ли она.

    • »
      »
      »
      9 лет назад, # ^ |
      Rev. 2   Проголосовать: нравится +19 Проголосовать: не нравится

      Считали ровно то же самое, но без вспомогательной динамики. Для dp[l][r] брали dp[l][r-1], если s[r] могло быть продолжением префикса "внешней" строки длины (r-l) % len, ну а если s[r] не подходит, или dp[l][r-1] == false, то последний символ подстроки точно не входит во "внешнюю", и нужно убрать суффикс длины k * len: dp[l][r] |= dp[l][r-k*len] & dp[r-k*len + 1][r].

  • »
    »
    9 лет назад, # ^ |
    Rev. 3   Проголосовать: нравится 0 Проголосовать: не нравится

    У меня решение аналогично решению Ильи + оптимизация, что если число букв в строке которую проверяем не матчится с числом букв на отрезке, то сразу говорим ответ. code Кто-то умеет делать для этого тесты, чтобы оно работало хоть как-то долго? (В Я.контесте зашло за 7ms.)

»
9 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Anything about A or B?