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

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

A

Итак, в этой задаче можно было просто выполнить то, что было написано в условии – перебрать все числа от A до B, для каждого из них перебрать все перестановки модулей и проверить, что не менее чем для 7 перестановок f(x)=x.

 

А еще можно было заметить следующее. Пусть p=min(p1,p2,p3,p4). Тогда если x<p, то, очевидно, при взятии любого модуля x не изменится, ведь он меньше любого модуля. Очевидно также, что в противному случае он изменится, потому что будет взят по определенному модулю, меньше или равному х. Таким образом, вне зависимости от перестановки модулей, для числа либо выполняется равенство f(x)=x, либо не выполняется. Некоторые участники просто проверили для определенной перестановки модулей, подходит ли каждое число из промежутка, и вывели количество чисел, для которых равенство выполняется. Однако достаточно было даже просто посчитать количество чисел в пересечении интервалов [0;p-1] и [a;b].

 

B

Пусть у нас после всех перераспределений энергии во всех накопителях установился уровень энергии, равный Х. Тогда очевидно, что все накопители, в которых было больше Х изначально, должны передавать энергию накопителям, в которых изначально было меньше Х. Таким образом, каждая частица энергии будет передана лишь один раз. Пусть изначально у всех накопителей, у которых было больше Х энергии, в сумме было Up, а всего их было A, а у остальных сумма – Dn, и их B=N-A. Тогда (Up-A*X)*(100-K)/100.0= X*B-Dn – то, что нужно заполнить, составляет 100-К процентов от того, что надо убрать. Ясно, что одна из сторон этого равенства будет возрастать, а вторая – падать, при изменении Х. Следовательно, можно реализовать двоичный поиск по величине Х, подсчитать левую и правую часть этого уравнения, и изменять границы в зависимости от того, какая часть больше.

На самом деле можно перебирать Х, равный только величине начальной энергии в какой-то точке, это можно сделать в целых числах, а затем на фиксированном промежутке между двумя значениями найти ответ аналитически. Любопытные могут вывести формулы самостоятельно.

 

C

            Авторы предполагали следующее решение задачи: последовательно перебираем количество топлива, которое течет по каждой трубе. В тот момент, когда значения топлива во всех трубах, идущих от или к какой-то вершине, уже определены, (если это не начальная и не конечная вершина) проверяем, что сумма топлива, которое втекло в узел, равна сумме топлива, которое из него вытекла.  Также надо было проверять, что сумма топлива, текущего из начальной вершины, не больше уже найденного лучшего ответа. Решение работает в пределах 30мс на всех тестах.

            Хотелось бы услышать, какое решение писали некоторые участники. Напоминает динамику по профилю?

 UPD: Оценка сложности. Ребер из первой вершины 5. Перебор всех возможных значений потока в этих ребрах - 65 Из каждой следующей на 1 ребро меньше, но надо учесть, что значение потока по последнему ребру определяется однозначно. Стало быть сложность 65 * 63 * 62 * 61 * 60 * 6 = 612 = 2176782336. Последний множитель - это проверка на то, что сумма входящих равна сумме выходящих. Это число велико, но участники сами могли убедиться, что при отсечении, что мы не рассматривает поток больший уже найденного, решение работает очень быстро.

E

Disclaimer: Я буду часто употреблять фразу «треугольник», подразумевая «точки, соотвествующие данному треугольнику».

 

Во-1, очевидно, что если два треугольника полностью совпадают, то имеет смысл их наложить.

Теперь предположим, что у нас нету полностью совпадающих треугольников.

Посмотрим на лучшее возможное расположение треугольников на плоскости, такое, что оно состоит ровно из оптимального числа точек.

Рассмотрим граф из 4 вершин, соответствующих треугольникам. Между парой вершин столько ребер, сколько общих точек у двух соответствующих треугольников.

Ясно, что этот граф связен. ( Пусть это не так. Тогда у нас есть два множества треугольников, не имеющие общих точек. Сдвинем одно множество так, чтобы у него была общая точка со вторым множеством. Ответ уменьшился. Противоречие. )

Посмотрим на графы в этом цикле.

Что значит, что есть цикл длины 2? Значит, у 2 треугольников две общие точки.

Что значит, что есть цикл длины 3? Значит, есть тройка точек, таких, что любые две принадлежат какому-то из трёх треугольников.

Что значит, что есть цикл длины 4 и нету циклов длины 2 и 3? Это значит, что есть 4 точки, такие, что любые две соседних принадлежат какому-то треугольнику. Этот случай можно рассмотреть отдельно – проверить, что можно выбрать по стороне от каждого из треугольников так, чтобы они образовывали 4угольник. Пускай мы его рассмотрели.

Итак, как мы можем перебрать все разумные расположения точек? Будем перебирать все порядки добавления треугольников. Пусть у нас уже добавлены некоторые точки. Может произойти одно из трех действий:

1). Мы просто добавляем наш очередной треугольник так, чтобы он имел общую точку со всеми предыдущими. К примеру, одна точка в (0,0), еще одна в (х,0), еще одна со строго положительной ординатой.

2). Мы нашли пару точек, расстояние между которыми равно стороне текущего треугольника. Тогда у нас есть не более 4 вариантов, как приставить его, чтобы его сторона совпала с отрезком, соединяющим две выбранные точки. Добавили, пошли дальше.

3). Мы нашли пару точек A B, таких, что можно найти такую точку С, что расстояния АВ и АС равны сторонам двух еще не добавленных треугольников соответственно. Добавляем эти два треугольника. Это соответствует либо циклу длины 3, либо 4 либо какому-то пути.

 

Проверяем что число точек в данный момент не превышает оптимального, переходим к следующему ( в случаях 1-2) или через 1 (в случае 3) треугольнику. И все)

 

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

 

Разбор задач Codeforces Beta Round 62
  • Проголосовать: нравится
  • +12
  • Проголосовать: не нравится

13 лет назад, # |
Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится
у меня по С просто тупой перебор, я перебирал ответ, а потом проталкивал через трубы. никакой меморизации =) вы рассчитывали на такое решение?
кстати, оно тоже работает 30мс
  • 13 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Не рассчитывали. Наши собственные такие решение ТЛили. Впрочем, я не думаю, что многим удалось сдать простой перебор, так что респект!:)
    • 13 лет назад, # ^ |
        Проголосовать: нравится +1 Проголосовать: не нравится
      эх у меня тупой перебор дал ТЛ, одно условие и AC =(
    • 13 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      UPD: Как выяснилось, среди авторских были и такие решения, пардон)
    • 13 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      У меня перебор лишь с отсечением по корректности потока через промежуточные вершины, но написанный рекурсивно => отсечение стало работать намного лучше => AC, правда лишь за 1,33с.
  • 13 лет назад, # ^ |
      Проголосовать: нравится +3 Проголосовать: не нравится
    На самом деле рассчитывали :) У меня такое же решение.
  • 13 лет назад, # ^ |
      Проголосовать: нравится +3 Проголосовать: не нравится
    На самом деле рассчитывали :) У меня такое же решение.
13 лет назад, # |
  Проголосовать: нравится +6 Проголосовать: не нравится
Тупой перебор - это же 6^15 вариантов в худшем случае?
  • 13 лет назад, # ^ |
      Проголосовать: нравится +8 Проголосовать: не нравится
    вот я тоже испугался 500 миллиардов операций и забил на эту задачу
    • 13 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      Ну если на ходу учитывать сохранение свойств потока, большинство этих случаев отпадают. Хотелось бы увидеть, сколько именно.
      • 13 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        ну ничего не предвещало, что "сохранение свойств потока" ускорит перебор минимум в тысячу раз
        • 13 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится
          У нас 4 условия, что сумма потока - 0. Таким образом 4 уравнения и 15 переменных - степеней свободы 11. А это уже жалкие 360 миллионов
          • 13 лет назад, # ^ |
              Проголосовать: нравится 0 Проголосовать: не нравится
            Еще можно было заметить, что всего через промежуточные вершины не может идти поток больше 10 (т.к. их степень 5, т.е. либо входящих, либо выходящих ребер не больше двух), а для "соседних с крайними" - не больше 5, что тоже, очевидно, отсекает немалое количество случаев. Теперь уже должно было быть очевидно, что пройдет либо тупой перебор, либо перебор + отсечение по ответу. Пишем обычный перебор, прогоняем программу на сервере при помощи кнопочки "запуск", получаем вердикт в 1,33с при TL в 3с, отправляем решение и переходим к следующей задачи.
      • 13 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        я чуть ниже написал, сколько таких случаев))
      • 13 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        ограничения намекали на перебор =) к тому же, можно же написать и попробовать погонять на своих тестах... пишется 10 минут
13 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
В задаче C я решил написать тупой перебор, который перебирает сколько там по трубам течет от 0 до 5 и, если что, откатывается. В итоге для n=6 получилось 2171148 валидных позиций (это когда втекает столько, сколько вытекает) - и все они находятся менее чем за 1 сек на моей машине.

Далее просто каждую такую позицию проверяем - подходит ли она под условия во входном файле и если да - пересчитываем ответ.

Решение прошло.
13 лет назад, # |
  Проголосовать: нравится -29 Проголосовать: не нравится
Задача С полный отстой!!! Когда автор задачи дает ее на контест он должен дать нормальное объяснение почему она работает(доказать асимптотическую оценку или показать что вылазит константа типа 1/(много)). В разборе этого не наблюдается :( 
  • 13 лет назад, # ^ |
      Проголосовать: нравится +13 Проголосовать: не нравится
    Автор ничего никому не должен. По ограничениям задача намекала на перебор. Участники могли сами написать решение и найти хучший тест для него. Впрочем, для особо недовольных напишу оценку сложности.
    • 13 лет назад, # ^ |
        Проголосовать: нравится +5 Проголосовать: не нравится
      блин, я думал, что в C действительно какие-то оптимизации нужны хитрые

      для сравнения: в 58-м раунде была задача D с малыми ограничениями, чтобы было понятно, что O(V· E2) проходит, несмотря на то, что авторское решение работает 50 мс на тестах с V ≤ 105, E ≤ 2· 105, но обладает такой же асимптотикой
    • 13 лет назад, # ^ |
      Rev. 2   Проголосовать: нравится +6 Проголосовать: не нравится
      После оценки асимптотики я понял что я не прав. До оценки асимптотики я считал что разбор задачи неадекватен(решение правильное потому что у нас работает 30мс).  
      • 13 лет назад, # ^ |
          Проголосовать: нравится +21 Проголосовать: не нравится
        Также прошу извинение за выражение что автор что-то должен. Я неправильно выразился. 
  • 13 лет назад, # ^ |
      Проголосовать: нравится +5 Проголосовать: не нравится
    Если переберать только ребра которые не соединяют сток и исток, а остальные дополнять жадно - то останется только 6^(4*3/2)= 46656 состояний. Умножив на проверку (6*6) выйдет чуть больше 1,5 млн. операций. 
13 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Асимптотика 5^m = 30517578125  в худшем случае 
13 лет назад, # |
  Проголосовать: нравится +3 Проголосовать: не нравится
Я задачу С решил перебором. Сначала взял сколько топлива всего у нас уйдет(0..36), потом пытался раскидать его по следующим вершинам (от первой сначала) до всех остальных согласно критериям. Ну а потом иду от второй и от нее раскидываю. В конце если нашли ответ то это и будет оптимальный ответ. Разбиений не так много получается и решение работает довольно быстро.
13 лет назад, # |
  Проголосовать: нравится -8 Проголосовать: не нравится
А когда планируется разбор на D?
13 лет назад, # |
Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится
В задачке С для меня очень неприятным оказался тот факт, что можно пустить 0 единиц жидкости... как то из фразы "найти минимальное количество топлива, которое, поступив в первый узел, сможет достигнуть синхрофазатрона" чувствуется что жидкость должна "достигнуть" синхрофазатрона... но если жидкости 0 - нечему достигать... Конечно тот факт что другим учасникам удалось сдать задачу говорит о том что проблемы с пониманием условия у меня... но было бы приятней если бы этот факт как то оговаривался в условии/сэмплтестах
  • 13 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Цитата из условия:

    Количество топлива, которое достигнет синхрофазотрона, не обязано быть положительным — оно может равняться нулю, если минимальные ограничения на количество топлива у всех труб равны нулю.
    • 13 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      Супер))) я тупо проигнорил это строчку)) и до сих пор не видел)) дамс... теперь понятно, спасибо
13 лет назад, # |
  Проголосовать: нравится +3 Проголосовать: не нравится
Условие задачи B некорректно (или чекер):
36 тест, ответ участника multisystem: 0.100001000;
Правильный ответ (математически и от жюри): 0.100000000
вердикт: WA
цитата из условия: "Абсолютная или относительная погрешность ответа не должна превышать 10 - 6"

Насколько я понимаю (это предположение), используется стандартный чекер, который сравнивает на строго меньше.
  • 13 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Опа! Если был использован стандартный чекер, то это палево даже не в чекере, а в testlib.h (версия 0.7.1).

    Кусок чекера выглядит так:

    if (!doubleCompare(j, p, EPS))
      quitf(_wa, ...);

    Кусок тестлиба где сравниваются даблы выглядит так:

    if(__testlib_abs(result - expected) < MAX_DOUBLE_ERROR)
    {
    return true;
    }

    • 13 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      Даже если вместо "<" поставить "<=", проблема остается. Возможно играет роль ошибка во время чтения при переводе из десятичной записи в двоичную.
      • 13 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        Вероятно, так и есть. Чекер, естественно, использовали стандартный.
  • 13 лет назад, # ^ |
    Rev. 2   Проголосовать: нравится +2 Проголосовать: не нравится
    Имхо, люди, которые пишут олимпиады по программированию должны осознавать, что при работе с вещественными числами компьютер почти всегда немного ошибается, в т.ч. и чекер, это нормально, требовать точных вычислений глупо, ограничение по погрешности в условиях всегда ставятся со значительным запасом.

    Такие строчки строчки в коде, как
    return res < 1e-6;
    printf
    ("%.9lf\n", ans+1e-6);

    показывают, что человек не понимает этого => заслуженный WA.

    • 13 лет назад, # ^ |
      Rev. 2   Проголосовать: нравится +5 Проголосовать: не нравится
      Я бы дополнил: это должны осознавать даже те люди, которые не пишут олимпиады, но занимаются программированием =)
    • 13 лет назад, # ^ |
        Проголосовать: нравится +3 Проголосовать: не нравится
      Это, конечно, да, понятно что епсилон дело тонкое. Но, с другой стороны, я всегда считал что в чекерах надо ставить раза в два меньшую точность чем в условии чтобы не было таких придирок.
      • 13 лет назад, # ^ |
        Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится
        По-моему, чекеры должны все-таки соответствовать условиям. Уж тем более в формате со взломами. Да даже и без взломов - такие чекеры делать все равно что слабые тесты давать из соображений благотворительности.
        Возможно, стоит явно оговорить, что решения с ошибкой меньше 1e-6 - 1e-8 верные, с ошибкой больше 1e-6 + 1e-8 - неверные, а остальные как повезет. (Погрешность погрешности написала от балды и только для примера; понятно, что она зависит от погрешности авторского решения).
        • 13 лет назад, # ^ |
          Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится
          Вы сформулировали проблему, о которой я хотел изначально написать более четко, спасибо.

          Ответ жюри всегда будет содержать ошибку, это нормально.
          Проблема именно со взломами, опишу ситуацию с раунда:
          Я смотрю на код, в котором написано ans + 1e-6, у меня есть тест на котором он ошибается на 1e-6 + 1e-8. С точки зрения условия, это корректный взлом, с точки зрения большинства участников, решение не корректно, но -50 совсем не хочется... (а в какую сторону ошибается ответ жюри не известно...).
        • 13 лет назад, # ^ |
          Rev. 3   Проголосовать: нравится 0 Проголосовать: не нравится
          Ну, не совсем так. Все-таки обычно если решение теряет точность то совсем, а ели оно вписалось двойной норматив то решение, скорее всего, принципиально правильное и это просто вопрос подстройки. Хотя, я согласен что это привычка с ACM-ICPC и для формата со взломами подходит плохо. По крайней мере, без каких-то предварительных договоренностей. А на сколько там будет оговорено допустимое отклонение точности от условия это не так и важно, можно 1%, можно 100%. Хотя, у 1% есть такой недостаток что точность же в условии тоже не с потолка берется и надо следить чтобы падение еще на два порядка не родило проблемы уже в самом чекере.