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

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

Сейчас идёт (уже прошла) VI интернет-олимпиада на сайте http://neerc.ifmo.ru/school/io/. Предлагаю после окончания обсуждать здесь задачи.

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

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

Это только у меня не заходит в веб-клиент или ещё у кого-нибудь такие проблемы? Пытался подключиться через обычный клиент, но постоянно "ошибка подключения к серверу". Может нужно его как-нибудь настроить? Может это из-за прокси сервера?

  • 13 лет назад, # ^ |
      Проголосовать: нравится +7 Проголосовать: не нравится
    Нет, это были временные лаги с сервером. К сожалению, такое у них частенько бывает :(
    • 13 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      Кстати, по-мойму уже заходит.
      • 13 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        Просим прощения за неудобства.
        К сожалению, в самый неподходящий момент начала олимпиады стало подходить к концу свободное место на сервере. К счастью, в этот раз мы были рядом и сразу начали исправлять. Но для этого пришлось на некоторое время прекратить прием задач. Это было в начале контеста, потому надеемся, что никому не помешало.
        В дальнейшем все прошло довольно гладко, только тестирование на полных тестах занимает немало времени (и чтобы не нагружать систему потому не проходит параллельно туру), потому результаты будут не сразу.
13 лет назад, # |
  Проголосовать: нравится +3 Проголосовать: не нравится
Вопрос по 1й задаче , там есть какой-то подвох? Мне показалась что она слишком легкая.
  • 13 лет назад, # ^ |
      Проголосовать: нравится +8 Проголосовать: не нравится
    Думаю да. Суммарный объем вывода может достигать 108, а это не мало.
    • 13 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      А как её тогда решать кроме как "в лоб"?
      • 13 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        Ну я на с++ putchar сделал на всякий случай. По идее у них быстрый сервак. Так как есть решения на паскаль(делфи), то думаю read в делфи должен успеть, следовательно может даже cout в с++ успеть
      • 13 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        Решил ее в лоб на Delphi. Все прошло на 100 баллов.
13 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Мне кажется,  вывод строк ответа никак нельзя ускорить.
  • 13 лет назад, # ^ |
    Rev. 3   Проголосовать: нравится +5 Проголосовать: не нравится
    Можно. Например выводить мало больших строк, а не много маленьких, объединяя строки через символ перевода строки, выводить с помощью gets  puts, а не cout или чего-то еще если на С++.
    • 13 лет назад, # ^ |
        Проголосовать: нравится +9 Проголосовать: не нравится
      Не слышал что в С++ можно выводить с помощью gets.
13 лет назад, # |
  Проголосовать: нравится +5 Проголосовать: не нравится
Интересно как решать 4ю, я придумал решение для |N-K|<=1, а дальше не знаю.
  • 13 лет назад, # ^ |
    Rev. 2   Проголосовать: нравится +8 Проголосовать: не нравится

    Доказывать эту формулу я не хочу, хотя и умею.

    UPD: буду рад увидеть формулу попроще.
    • 13 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      Дааааа, до такого я бы точно не додумался. ))
      • 13 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        На самом деле страшная С-шка внутри это раскрытое количество разбиений на неотрицательные слагаемые. А числа и  
        Вылазят достаточно естественными способами.
    • 13 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      А можно узнать, где Вы взяли такую формулу? Я пробовал вывести формулу, но безуспешно!
      • 13 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        Вывел. 

        Общая идея вывода - надо знать кое-какую теорию, и посчитать количество разложений, которые переходят в себя при цикл сдвиге на данное количество.
        Но я почти уверен, что можно и без этого.
  • 13 лет назад, # ^ |
    Rev. 2   Проголосовать: нравится +8 Проголосовать: не нравится
    Вот ещё моё решение. На самом деле, если очень глубоко покопаться, оно совпадает с Пашиным, просто я расписал покороче ту же формулу (которая, кстати, следует из леммы Бёрнсайда, групповая структура налицо).

    Как можно было рассуждать.

    Разобъём все разбиения (каламбур!) на классы эквивалентности относительно циклического сдвига.

    Рассмотрим главный период A в разбиении. Понятно, что A | k. Также понятно, что размер класса эквивалентности для этого разбиения сопадает с A.

    Пусть F(A) - количество разбиений с главным периодом A. Тем самым получаем, что ответ X = sum(F(A), A=1..k) = sum(F(A), A | k), т.е. F(A) при A не делящем k есть ноль.

    Пусть G(a, b) есть количество разбиений числа a на b положительных целых слагаемых. Известным образом оно равно биномиальному коэффициенту C(a + b - 1, b - 1).

    Выведем рекуррентную формулу для F(A). Заметим, что любое разбиение с главным периодом A однозначно задаётся своими первыми A числами, которые в сумме должны давать n / A (тем самым, F(A) при A не делящем n тоже равно нулю). Значит, F(A) = G(n / (k / A), A) - sum(F(B), B | A), т. к. мы посчитаем также все разбиений с кратным периодом.

    Теперь про асимптотику. Можно рассматривать только делители, например, n, которых не больше тысячи. Получаем решение за O(d(n)^2), где d(n) есть количество делителей числа n.
    • 13 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      Всё тривиально считается по модулю, благо тот простой.
      К слову, O(d(n) ^ 2) это круче чем O(n), потому что d(n) = o(sqrt(n)). Поэтому ещё чуть-чуть и решение Паши начнёт ТЛится, а моё - ещё летать.
      • 13 лет назад, # ^ |
        Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

        • 13 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится
          Если быть точным, для любого сколь угодно малого k d(n) = o(n^k).
      • 13 лет назад, # ^ |
          Проголосовать: нравится +5 Проголосовать: не нравится
        Тебе все равно нужно O(N) факториалов, а это самое времязавтратное место. Оно работает раз в 10 дольше чем остальная часть решения.
        • 13 лет назад, # ^ |
          Rev. 2   Проголосовать: нравится +5 Проголосовать: не нравится
          Вот неприятность. Об этом я как-то забыл. Даже не O(N), а O(P).
          UPD: А точнее O(min(N, P)).
          • 13 лет назад, # ^ |
              Проголосовать: нравится 0 Проголосовать: не нравится
            Я получал Cnk за log быстрым возведением, если это можно за О(1) расскажите как плиз.
            • 13 лет назад, # ^ |
                Проголосовать: нравится 0 Проголосовать: не нравится
              Можно. Для этого надо предподсчитать все факториалы и обратные к ним.
              • 13 лет назад, # ^ |
                  Проголосовать: нравится 0 Проголосовать: не нравится
                Стоп но нам же там потребуется 10^6 факториалов на log а в нашей задаче мы делаем меньше а именно sqrt(n) * log т.к. вычисляем Cnk только для корня из n случаев по одному разу. Или ты имеешь в виду как то на лету вычислять следующее из предыдущего?
                • 13 лет назад, # ^ |
                    Проголосовать: нравится 0 Проголосовать: не нравится
                  10^6 факториалов - не так уж и много. Обратные у ним считаются примерно за секунду.  Сильно быстрее я думаю все равно не получится.
    • 13 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      Мне кажется, что вместо F(A) = G(n / (k / A), A) - sum(F(B), B | A) должно быть F(A) = G(k / (n / A), A) - sum(F(B), B | A).

      • 13 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        Нет. Всего k / A кусков длиною в A, в каждом, значит, сумма n / (k / A).
13 лет назад, # |
  Проголосовать: нравится +5 Проголосовать: не нравится

Вот, что сделал я:

Задача А.

Нужно просто сделать всё так, как сказано в условии.

P.S. Если пишите на С++, не нужно использовать cin/cout – будет ТЛ.

 

Задача B.

Заведём булевский двухмерный массив изначально равный нулю. Потом при добавлении каждого корабля на карту проверяем ни пересекается ли новый корабль с каким-нибудь старым. Если пересекается выводим «INCORRECT». Для удобства перед добавлением очередного корабля можно увеличить его размеры на 1 в каждую сторону, а в конце останется посчитать количество клеток равных нулю.

 

Задача С.

Простое рекурсивное решение. Изначально проверяю: если количество пустых клеток ни делится на 4 вывожу NIE. Дальше вызываю рекурсию и пока нужно добавлять фигурки перебираю все возможные на все возможные позиции с всеми возможными поворотами.

P.S. хотелось бы увидеть разбор по D.

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

    мне кажется перебор тут не совсем проходит, ну например, как долго у вас работает ваше решение на тесте

    6 6
    1 2 0 1 2 3 3
    ...#..
    ##....
    ......
    #.....
    ......
    ......

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

      Да, действительно - ответа я не дождался.

      Кто-нибудь может объяснить нормальное решение?

      • 13 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        У меня зашёл лобовой перебор (тут он тоже работает 0.1 секунды): перебираем для каждой еще пустой клетки (по очереди), какую фигуру поставим и с каким поворотом. Если можем - ставим (помечая клетки занятыми) и продолжаем перебор. Если нет - возвращаем false.
    • 13 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      У меня на этом тесте <0.05 sec работает. По логике вещей это не самый плохой тест. Самый плохой это тот, в котором на каждом шаге перебора идёт выбор из всех 19 возможных фигур, однако ответа не существует, например такой тест:


      6 6
      9 9 9 9 9 9 9
      ......
      ......
      ......
      ......
      ......
      .....#


      На нём, если не ставить проверку на чётность, у меня работает 0.38 sec.

      К слову, мой перебор в TL укладывается вполть до поля 7x7.
13 лет назад, # |
  Проголосовать: нравится +3 Проголосовать: не нравится
"Сейчас идёт IV интернет-олимпиада" - по-моему это 6, то есть VI интернет-олимпиада
13 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Что-то мне подсказывает, что многие сдадут по 3 первые задачи, а разница будет только в 4ой задаче, что ни есть good.
  • 13 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    еще думаю будет много людей с 85-95 по первой.
    • 13 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      Тех которые пользовались cin/cout ?
      • 13 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        Да. Еще бывает putc, printf, которые тоже могут немного не успевать. Хотя в общем-то могу только гадать. Возможно у жюри просто нет тестов на которых слишком большой вывод, просто об этом забыли написать в условии.
        • 13 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится
          Да, действительно, у жюри, к счастью, нет тестов с большим выводом. Хотя стоило конечно это написать в условии или просто сделать ограничения меньше.
          Радует, что тебя это заставило задуматься и пооптимизировать ;)
13 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
В процессе подготовки этой олимпиады в последний момент одна задача была убрана из олимпиады, поскольку очень понравилась жюри! Ожидайте ее появления на более серьезных соревнованиях! ;)
13 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Очень жаль, что я забыл, что вычитание по модулю тоже нужно делать)) Из-за этого слил 40 баллов. А так, огромное спасибо за последнюю задачку, очень понравилась =)
  • 13 лет назад, # ^ |
      Проголосовать: нравится +5 Проголосовать: не нравится
    Стиль последней задачи навеян польскими контестами (которые, например, дают на петрозаводских сборах) - они любят дать задачу посчитать количество способов сделать что-то с точностью до чего-то по модулю какого-то простого числа, данного во входном файле :)
    По этой же причине в задаче про тетрис ответ надо было вывести на польском языке ;)