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

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

Итак, совсем недавно завершился первый раунд Snark News Summer Series. Предлагаю тут его обсуждать, а также напишу небольшой разбор.


Задача А

Вероятно, самая простая задача раунда, с которой и начали большинство участников. Для ее решения следовало заметить, что существует ровно свободных бит в палиндромах с длиной битовой записи Х - биты, начиная с второго по сташинству, до середины строки. То есть палиндромов с длиной битовой записи Х всего . Таким образом можно узнать длину битовой записи палиндрома, который нам нужен, и номер нашего палиндрома среди всех палиндромов такой длины. Ну а само число тогда получить уже очень просто:
1). Пусть S - первая половина искомого палиндрома. Тогда ее старший бит - 1, а следующие биты - это двоичная запись номера нашего палиндрома, дополненная сначала нулями так, чтобы длина S была равна X / 2 + X%2.
2). Ответ - это S + S', если длина палиндрома четная, S' - перевернутая строка S. Если длина нечетная, то у S' надо просто откусить первый символ.

Интерестно, есть ли решение формулой.

Задача Б

Пожалуй, эта задача мне понравилась больше всего. Как раз то, что надо как одна из 6ти на 80 минут - немного покодить, немного подумать, есть, где допустить баг.

Для начала надо было запомнить все сгибы листка, которые происходили в действительности (то есть линия сгиба проходила не за листком) и записать координаты 4 углов после каждого такого сгиба.
Затем надо было пройти с конца по этому массиву, храня на каждом шагу  множество дырок в листке, и переходя к множеству дырок на развороте листка. 
Как мне кажется, падали участники на том, что не проверяли, что после разворота точки находятся по-прежнему на поверхности листка. Недостаточно также было возвращать те точки, которые после всех разворотов находятся на изначальном листке - в процессе разворачивания могли возникнуть фиктивные точки, которые потом попали на изначальный листок.

Задача С

Я эту задачу, как и многие другие, решал паросочетанием. Можно заметить, что четность суммы координат клетки, где стоит конь, и тех полей, куда он бьет, различна. Таким образом можно разбить все поле на два типа клеток, и проверсти ребра между теми парами невырезанных клеток, в которые находятся на расстоянии хода коня друг от друга. После этого в полученном графе построить максимальное паросочетание и поставить коней на паросочтенные клетки одной из доль (то есть только с четной суммой координат, к примеру). Могло показаться, что паросочетание не пройдет, но это заблуждение:) Тут 5000 вершин, из каждой по 8 ребер. В Харькове за 3 секунды почти все участники пропихнули паросочетание на 50000 вершин, из каждой из которых было 32 ребра (2011 год, 9 день, "Регулярное паросочетание").

И еще мне кажется, что тут проходила какая-то жадность. Идеи?

Задача Д

Не люблю такие задачи. 25с, 666 тестов. Непонятно, должно ли решение выполнять макстест на 25/666 с., или в файле не будет много макстестов, и пройдет какой-то пропих. Я пытался сдать в дорешивании динамику по подмаскам и перебор, оптимизированный запоминанием. Перефразируя Томаса Эдисона, я не зафейлил - я написал 26 кодов, которые делают что-то другое:)

ПС. Хотелось бы услышать, как сдавали те, кто сдали.

Задача Е

Неплохая задачка, но, по-моему, ограничения чуть-чуть переподкручены. Решение - две динамики:
F[V, M] - максимальный поток, могущий идти вверх из вершины V если мы на ее поддерево потратили M миллионов. (Пропускная способность ребра над этой вершиной не учитывается.)
G[V, M] - максимальный поток, могущий идти по ребру от вершины V вверх, если мы на ее поддерево и на ребро вверх от нее в сумме потратили M миллионов.

Ну и переход изящен и самоочевиден:
ПС: Если не самоочевиден - деньги вершины надо разделить между левым и правым поддеревом и ребром в поддерево. Деньги вершины и ребра в нее надо разделить на деньги в вершину и деньги, потраченные на ребро.
L, R - правый и левый потомок вершины. Для листьев F[Leaf, M] = C[Leaf] + M, где C[Leaf]- количество изначально вырабатываемой в листе нефти.


Что раздражает - другое, более сложное решение, с такой же ассимптотикой O(N * M2) не прошло по ТЛу, такое же решение, только не двумя циклами, а двумя функциями, которые друг друга вызывают - тоже. Это зашло меньше чем за 3с. при ТЛе в 4.

Задача Ф

Ну, построить двудольный граф по правилу "если в инпуте есть ребро i → j, то провести ребро из вершины i левой доли в вершину j правой", построить максимальное паросочетание и вывести его, если оно совершенное. Хм. Где-то выше я это уже писал. По-моему. И по-моему давать в одном контесте две задачи, которые решаются одним и тем же алгоритмом (хотя, может, могут быть решены и по-другому) - незачет.

Еще сильно расстроил плохой тест по задаче Е - я-то с ним только в дорешивании боролся, а вот участники врея потеряли.
  • Проголосовать: нравится
  • +20
  • Проголосовать: не нравится

13 лет назад, # |
  Проголосовать: нравится +1 Проголосовать: не нравится
У меня в Е два цикла, и по времени прошло. Это на С++.
Тоже показалось странным, что две задачи на паросочетание, но я это списал на то, что С, возможно, и не была на паросочетание по задумке.
Кстати, я на С получил ТЛ, когда не расставлял ребра жадно до запуска паросочетания, а запускал поверх пустого графа.

Интересно, что почти все пишут контесты в последний день :о) Я за последние сутки с небольшим упал с 8-ого места на 18-ое.

  • 13 лет назад, # ^ |
      Проголосовать: нравится +1 Проголосовать: не нравится
    Чтобы было больше статистических данных. 
    *Я не помню, сабмиты в светлую сразу с результатами показываются во время написания виртуального контеста? Если да, то это куча инфы про то, насколько задача хитрая, сколько не могут сдать с первого раза, и стоит сдавать всветлую или втемную*

    А про Е я и написал, что два цикла проходят, а две функции уже нет. Тоже С++.

    В С - я сразу кодил за , и с жадностью вначале. Оно на самом деле очень крутая эвристика, раз в 5 ускоряет где-то(а уж на таком разреженном-то..), как-то тестировали вроде.
  • 13 лет назад, # ^ |
      Проголосовать: нравится +9 Проголосовать: не нравится
    Хм. А у меня в С просто обычный Кун без жадностей вначале зашел.
  • 13 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    А каким алгоритом паросочетание? 
13 лет назад, # |
Rev. 3   Проголосовать: нравится +4 Проголосовать: не нравится

[Здесь было неверное решение задачи D]
  • 13 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Мне кажется еще нужно знать, что стоит на первом и втором месте.
    • 13 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      Ну очевидно, начальные состояния просчитываются "в лоб" перед запуском динамики
      • 13 лет назад, # ^ |
        Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

        я не понял, как будет ставиться последний элемент в кругу(проверяться, что сумма последнего первого и второго -- простое число)
        • 13 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится
          Оказывается, я тоже не понял =) Спасибо, что заметили. Самое первое, что приходит на ум - ставим первые 2 числа перебором, а потом запускаем искомую динамку
          • 13 лет назад, # ^ |
            Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

            Просто в дорешивании тоже самое делал, ничего лучше пока нет, ну это понятно таймлимится.
13 лет назад, # |
Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

Не обращайте внимание. Память подвела :)
13 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
В задаче D данные числа могут быть отрицательными или нулями? (в условии про это ничего не сказано)
  • 13 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Каждый тестовый пример состоит из одной строки, состоящей из целых положительных чисел... не превосходящих 100.
    • 13 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      Спасибо, несколько раз читал условие, но так и не обратил внимание на эту строчку (
13 лет назад, # |
Rev. 2   Проголосовать: нравится +6 Проголосовать: не нравится

Как я сдал D на дорешивании: сортировал данный набор чисел по убыванию и начинал перебор (понятно, что большие числа должны стоят ближе к началу и наоборот). Перебирал сначала первую позиция искомой линейки чисел, потом вторую и т.д. Отсечение по непростоте трёх подряд идущих чисел и если наилучший расклад даёт сумму большую, чем уже найденная. Наилучший расклад - это значит, что множество чисел, для которых еще предстоит определить позицию, сортируется по убыванию, после чего для него вычисляется сумма - скальное произведение с вектором [i,i+1,...,n] (для каждой подмаски набора чисел эту сумму предподсчитываем до начала перебора).
Тестировал локально на макстексте, получалось около 10 минут, если не больше. Послал на сервер - прошло.
  • 13 лет назад, # ^ |
      Проголосовать: нравится +4 Проголосовать: не нравится
    Ну это тогда вообще бред, что из тех 666 тестов только пара штук больших, а остальные все маленькие. Зачем тогда давать такие ограничения? Если авторское решение работает при данных ограничениях, то почему бы не дать такой тест, который отсекал бы неоптимальные решения? Если же нет, то вообще непонятно, из каких соображений были выбраны эти ограничения.

    Это относится не к вам, а к авторам контеста.
    • 13 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      Тогда такой же вопрос можно задать авторам задач финала ICPC :) (про прочие китайские и испанские контесты уже говорить и не стоит)
      • 13 лет назад, # ^ |
          Проголосовать: нравится +1 Проголосовать: не нравится
        Хм, а разве на последних финалах было такое, что заходила лажа, которую можно почелленджить? На древних такого конечно полно, но на современных вроде всё нормально.
        • 13 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится
          Да, соглашусь, на последних надеюсь все в порядке. Имел ввиду как раз старые финалы. Хотя вот не уверен про финал 2005, там вроде было что-то не так с задачей D (которую сдали чемпионы китайцы).
    • 13 лет назад, # ^ |
        Проголосовать: нравится -7 Проголосовать: не нравится
      Вряд ли Снарк сам придумывает эти задачи, вроде бы он берёт их с каких-то неизвестных в России контестов, а там такое не редкость.

      Хотя в том, чтобы помещать в один файл сразу все тесты и давать большой TL есть своя логика: пусть участники не подгоняют решение под таймлимит, а пишут такое, которое работает максимально быстро. При этом, возможно, программы, за адекватное время обрабатывающей входной файл из одних макстестов, и вовсе не существует
    • 13 лет назад, # ^ |
        Проголосовать: нравится +4 Проголосовать: не нравится
      Когда уже в Англии прекратятся беспорядки.

      Это относится не к вам, а к правительству соединённого королевства.
13 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
off-topic:
куда нужно писать "жалобу", если через тот пароль что пришел и тот логин что я им поставил за рекомендуемый не заходит?
13 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
У меня, наоборот, самая короткая задача по количеству кода получилась B.
Т.к. координаты небольшие (10000) то можно завести два массива (для x и y сгибов), где в каждой ячейке (координате) хранится кол-во слоев, их можно заполнить независимо друг от друга эмуляцией сгибов, результат - произведение соответствующих ячеек для х и y прокола.