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

Автор Jokser, 14 лет назад, По-русски
Обсуждаем задачи тут.
Я участвовал в Div.2.
И меня интересует, почему Дейкстра с сетом дает WA#16 в G.
И хэширование + дп + бин.поиск дает WA#2 в J.
Я уже просто запарился искать ошибку.
  • Проголосовать: нравится
  • 0
  • Проголосовать: не нравится

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

Интересует, как сдавать F с первой попытки))

И ещё, как в J обойти ограничение по памяти, если строить решение на хэшах (по моим подсчётам 8 * 10 000 * 10 000 / 2 как бы многовато, а писать хэши на 4 байта как-то стрёмно да и это тоже еле влезет).

  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    А как делали её?
  • 14 лет назад, # ^ |
    Rev. 3   Проголосовать: нравится 0 Проголосовать: не нравится

    В условии было сказано что суммарная длина всех текстов не превышает 10000, следовательно хэшировать строк нужно будет меньше, т.к. k2 можно ограничить как k2 = min(k2, n, m).

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

    После этого был оквадратичное ДП, которое можно было свести к n*log(n) RMQ.

    Формирование наибольших префиксов суффиксов содержащихся в 1й строке у нас занимало чуть больше секунды, квадртичное ДП работало примерно за такое же время => наша команда отхватывала TL. Предположительно дп за н лог н решило бы проблему, но было 5 минут до окнца контеста %)

    ЗЫ Важным моментом было то что набо дыло уметь обнулять все массивы за О(1)

    ЗЫ2 Данный пост не претендует на правильное решение %)

    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      хэши таки долгие. мы кое как затолкали J хэшами на предпоследней минуте с 14 попытки.

      скорее всего по-нормальному J решается через какие-нить суффиксные автоматы или какой нибудь ахо-корасик.
      • 14 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        Решали J при помощи сжатого суффиксного дерева, которое строится за O(n^2), но занимает O(n) памяти.
      • 14 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        мы делали через z-функцию(их там n-штук) и вышеупомянутую динамику. 
      • 14 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        Мы писали её как динамику и КМП на каждом шаге динамики для нахождения наибольшей длины префикса второй строки, содержащегося во второй. На тесте
        5000 5000 1 5000
        a x 5000
        a x 5000
        задача работает чуть меньше секунды (если собирать при помощи g++ -O -march=pentium4m, иначе работает секунды 3)
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    а как F делали?
    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      Добавляем по одной букве. Если есть буква, которую можно добавить к текущей строке, чтобы получить то, что нужно, добавляем и пишем ответ. Иначе добавляем случайную букву. Повторять с начала до тех пор, пока ответ не найдётся :D
    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      мы написали честный BFS по всем возможным значениям хэша. т.е. вот у нас есть вершина - хэш некоторой строки (+ еще тут храним 1ю букву и ссылку на вершину - суффикс этой строки). дописываем в начало всевозможные буквы, получаем новые вершины. получили нужный хэш - восстанавливаем строку и выводим.
      итого решение за 10^7*26. нужно быть очень аккуратным с константой.
      • 14 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        Мы писали так же, и очень долго пихали это в TL. В итоге зашёл вариант, в котором вообще не было взятия остатка по модулю q.
    • 14 лет назад, # ^ |
        Проголосовать: нравится +1 Проголосовать: не нравится

      У нас прошло такое решение:

      1) Перебираем первые четыре буквы слова - это 264 вариантов.

      Вычисляем хеши от этих строк из 4-х букв.

      Запоминаем для каждого хеша, как мы его получили.

      2) Затем генерируем случайную строку из 25-35 символов, первые 4 символа которой делаем нулевыми.

      Вычисляем от неё хеш и смотрим, сколько надо добавить, чтобы получить нужное значение.

      Если такое число было среди заранее вычисленных хешей для первых четырёх символов, то ставим эти символы и выводим ответ, иначе генерируем новую случайную строчку.


      Это решение, как мне кажется, можно ещё немного модифицировать: брать не первые четыре символа, а, например, 1-ый, 42-й, 99-й и 167-й (когда мы берём первые четыре, а основание p - маленькое, то будет много коллизий среди этих 264 хешей). И в случайной строчке несколько букв зафиксировать, а генерировать несколько как-то разбросанных по ней.

      Количество перебираемых вначале букв тоже можно изменить.

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

      • 14 лет назад, # ^ |
          Проголосовать: нравится +3 Проголосовать: не нравится
        Вот еще простое решение. Мы перебирали все строки вида xaa...aay, то есть перебирали фактически длину строки и последнюю букву, а первую подгоняли если были близко к нужному хешу. Получалось 10^6*26*26 вариантов и сдалось с первой попытки.
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Во-первых 5000 * 5000 / 2, а во вторых ты где-то логарифм потерял, тебе же хэши надо посортить или в set сложить. В любом случае n^2 log(n) это уже перебор. Надо решать c помощью z-функций за чистый квадрат.

    Но в идеале есть решение вообще за линию с помощью суфдерева и идеи монотонности при построении ответа.
    • 14 лет назад, # ^ |
      Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится
      хэши складываются в другой хэш :) Получается чистый квадрат, но с большой константой.

      хэш-таблица оно называется
      http://ru.wikipedia.org/wiki/%D0%A5%D0%B5%D1%88-%D1%82%D0%B0%D0%B1%D0%BB%D0%B8%D1%86%D0%B0
      • 14 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится

        Да, я понял свою ошибку. Я зациклился на том, что первая строка может быть ~10000, но не подумал, что такие длинные подстроки в этом случае уже не могут встречаться во второй строке. В общем в таком случае k2 = min(k2, длина второй строки) и проблема с памятью решается. А запихать хеши - это уже дело техники и кучи штрафов. Другого выбора не было, т.к. с z-функцией пока подружиться не довелось)

        • 14 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится
          на самом деле 5000 * 5000 / 2 элементов для хэш-таблицы многовато, да и коллизии испортят всю константу. таким образом, туда надо пихать не все сразу, а в некотором порядке, периодически очищая хэш-таблицу.

          эх... если бы у нас тогда промелькнули в голове слова наподобие "z-функция" или "префикс-функция")) не страдали бы такой фигней в последний час
      • 14 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        То есть вы что-ли хэш с коллизиями реализовываете для хранения начальных хэшэй? Думаю там константа будет порядка того же логарифма.
        • 14 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится

          Ну мы вообще до реализации не дошли) Я лично планировал N^2 logN пихать, судя по отзывам это было наивно)))

          Но вообще такую тему с хэш-таблицей на некоторых задачах с тимуса удавалось пропихнуть.

        • 14 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится
          ну, тем не менее, таким образом задачу мы запихали :)
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Расскажите как К (2 див.) решать?
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Пусть есть набор чисел, сумма которого это степень двойки. Тогда в нем четное количество нечетных чисел. Разобьем их на пары любым способом и применим в каждой паре эту операцию. Тогда все числа станут четными. Поделим все числа на два. Сумма опять останется степенью двойки. И мы можем повторить тоже самое. В конце получится куча нулей и одно числа равное сумме всех. Всего за <=K*N/2 операций, где сумма всех чисел равна 2^K.
    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      А почему обязательно сумма должна быть степенью двойки? Например, сложить числа 3 и 9 можно.
      • 14 лет назад, # ^ |
          Проголосовать: нравится +3 Проголосовать: не нравится
        Можно. Я имел ввиду, что сумма всех чисел набора равна степени двойки. Там же это дано по условию.
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
В G у нас динамика, выбираем  минимум для каждой клетки по строке и по столбцу Хотя видимо Дейкстра должен работать.
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
расскажите как решать B. у нас есть решение за O(N*N*25 + 100*25*T)
25 - это количество простых чисел меньше 100. как быстрее - непонятно. прекальк тоже в 64 Кб не лезет.
  • 14 лет назад, # ^ |
      Проголосовать: нравится +5 Проголосовать: не нравится
    Количество решений уравнения из этой задачи - это просто количество разбиений n на неупорядоченные слагаемые. Его можно вообще говоря считать быстрее, чем за O(n^2). Например, следующим образом. Рассмотрим производящую функцию результата. Она будет иметь вид (1+x+x^2+...)*(1+x^2+x^4+...)*(1+x^3+x^6+...)*... = 1 / ((1-x) * (1-x^2) * (1-x^3) * ...). Заметим, что если в знаменателе раскрыть скобки, то получится ряд, у которого очень мало ненулевых элементов (а точнее, ненулевые коэффициенты только при x в степени q*(3q+1)/2 и q*(3q-1)/2 (при этом если q чётное - то 1, иначе -1)). Это можно не очень сложно доказать, но мы на контесте просто заметили закономерность. Значит, ненулевых коэффициентов O(sqrt(n)), и обратить ряд можно за O(n*sqrt(n)). Предпросчёт для всех простых до 100 и китайская теорема об остатках дают итоговое решение.
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    25 превращается в 2, если поумножать простые друг на друга.
    N превращается в как-то так:
    http://en.wikipedia.org/wiki/Partition_%28number_theory%29
    http://en.wikipedia.org/wiki/Pentagonal_number_theorem
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Расскажите как решать E
  • 14 лет назад, # ^ |
      Проголосовать: нравится +10 Проголосовать: не нравится
    Следует рассмотреть 2 случая, когда количество сторон четно и нечетно. В любом случае, если многоугольник описанный, то точки касания делят стороны на 2 части. Обозначим стороны a[i]. Пусть сторона a[i] делится на кусочки x[i] и x[i + 1] (нетрудно видеть, что соседние кусочки на соседних сторонах равны). Тогда если n - количество сторон нечетно, то x[1] выражается через a[i]. Если n четно, то из системы x[i]+x[i+1]=a[i], для i от 1 до n, x[n+1]=x[1], можно найти, что x[1]<a[1], x[1]>-a[2]+a[1],x[1]<a[3]-a[2]+a[1], и так далее. Тогда, выберем любое x[1] подходящее ограничениям. После выбора x[1] выразим все остальные кусочки. Если x[i]<0 или x[i]>a[i] то тогда ответ NO. 
    Иначе, если радиус окружности вписанной в многоугольник равна R, то тогда единственное условие на то, что такая вписанная окружность существует, это 2*arctan(x[1]/R)+2*arctan(x[2]/R)+...+2*arctan(x[n]/R)=2*Pi (слева сумма углов из под которых видны стороны многоугольника из центра). Далее нетрудно понять, что слева функция монотонна и искать искомый радиус следует бинпоиском. А зная радиус и точки касания уже легко восстановить координаты вершин многоугольника.
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Задачи B и F не понравились :о)

 

Кто-нибудь знает/есть идеи как решать задачу D?

 

  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    С F ещё понятно, а чем не понравилась B? Красивая идея, несложная реализация.
    • 14 лет назад, # ^ |
        Проголосовать: нравится +5 Проголосовать: не нравится
      Скорее всего тем, что почти все ее гуглили)
      • 14 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        Ну те кто гуглили - сами себе злобные бакланы. На онсайтах гуглить нельзя, так что они потеряли возможность потренироваться, не говоря уж о моральной стороне вопроса. Почему из-за каких-то читеров задача должна не нравиться - непонятно.
        • 14 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится
          согласен, Гуглить нехорошо)) надо тренироваться)))
    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      А мне как раз непонятно чем F не понравилась? Красивая задача на bfs...

      В B нам не понравилось то, что не зная формулы Эйлера (ну и вообще идеи про производящие функции) ее непонятно как придумать - мы за 3 часа не смогли :(
      Удивило количество команд, сдавших ее - потому я думал, что там что-то более очевидное...
      • 14 лет назад, # ^ |
          Проголосовать: нравится +5 Проголосовать: не нравится
        Мне F не понравилась тем, что из-за неаккуратной реализации там очень просто получить TL, и приходится оптимизировать в константу раз. Сделали бы уж ограничения поменьше, чтобы как угодно написанное правильное решение проходило. Моё субъективное мнение: задачи на неасимптотические оптимизации - не совсем то, что надо давать на контест.
        B прекрасно придумывается даже если не знать формулы (хотя про производящие функции мы знали, но думаю, это не очень секретное знание, подозреваю, что на математическом факультете любого вуза про них рассказывают). Тем более появляется дело для математика в команде, способное занять его на сколь-либо существенное время :)
        • 14 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится
          Видимо, нам повезло с F - тормозила только проверка правильности ответа, убрав которую, все прошло.
          Интересует вопрос про эту задачу - какой максимальной длины там возможен ответ?

          Мы опять вдвоем писали и не было математика - потому с В были проблемы :(
          • 14 лет назад, # ^ |
              Проголосовать: нравится 0 Проголосовать: не нравится
            Вспоминая свой код - длина ответа точно <20, иначе он бы упал с RE :) Ну а из общих соображений коллизий там очень мало, так что вряд ли даже 10 достигается.
            • 14 лет назад, # ^ |
              Rev. 3   Проголосовать: нравится 0 Проголосовать: не нравится
              Мы писали что-то типа Meet In The Meedle на длину 9 (больше давало TLE) - получали WA 47. Когда потестили, поняли, что работать это не будет при маленьких p - очень медленно заполняется диапазон 0..q в зависимости от длины строк.
        • 14 лет назад, # ^ |
            Проголосовать: нравится +5 Проголосовать: не нравится
          > подозреваю, что на математическом факультете любого вуза про них рассказывают
          Могу точно сказать, что это не так. 

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

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

          Что касается оптимальности реализации - безусловно, нужно приучать участников писать свои решения оптимально, но без фанатизма. Например, участники должны понимать, что cin работает долго и нужно использовать другие способы для чтения больших объемов данных. Но требовать каких-то супер ухищрений для пропихивания асимптотически правильного решения нехорошо. В задаче F, на мой взгляд, ограничения были выставлены слишком жестко, поэтому она тоже не понравилась (главным образом двум Диманам, которые убили на нее полконтеста).
    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      Мне не нравится задача когда

      а) Моих знаний до контеста не хватает, чтобы ее решить

      и

      б) После контеста, прочитав разбор, я не хочу пополнять эту дыру в знаниях.

      Потому что такая задача не вписывается в мои субъективные представления о том, какие должны быть задачи на соревнованиях :о)

       

       

      • 14 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        Думаю, ты преувеличиваешь - про производящие функции ты наверняка слышал, а дальше на программистском уровне (без доказательств) всё придумывается (по крайней мере, мы придумали).
        Ну не должен же быть весь контест из тупых задач с длинными решениями, красивая математика никогда не помешает.
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Как решать задачу H?
Казалось бы, задача сводится к онлайн задаче найти точку в прямоугольнике, либо оффлайн найти максимум в прямоугольнике. А какую структуру данных использовать?
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Двумерное дерево интервалов. Оно не заходит по времени, так что приходится применять комплект хаков. У нас финальной "отсечкой" было следующее: если мы сходили в левое поддерево и получили значение, большее того, с чем мы собираемся сравнивать весь результат запроса, то в правое поддерево не идти. Ну и кроме этого надо было аккуратно написать.
    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      Мы находили точку в прямоугольнике, использая структуру данных похожую на кд-дерево, на удивление решение прошло ТЛ практически без оптимизаций.
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    ну вот мы использовали сумму на прямоугольнике фенвиком, у нас не проходило в TL как мы не упихивали..... Еще мне рассказывали, что есть решение на O(nlogn) и O(n) их рассказывали на разборе в СПБГУ... если расскажут, и я узнаю как решается, тогда напишу=))
    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      Да, Серёжа умеет за О(n log n) решать, он и на петрозаводских сборах рассказывал каких-то, как =)
      • 14 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        Надо бы его спросить как =) всё таки задача интересная =)
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Как решается С?
  • 14 лет назад, # ^ |
      Проголосовать: нравится +3 Проголосовать: не нравится
    Надо заметить, что можно никогда не прыгать. Ну в самом деле, если мы прыгнули, то почему бы вместо просто не сходить той блохой, через которую прыгали?
    Любители инвариантов могут посчитать что-то типа минимального возможного расстояния от блохи до собаки и заметить, что оно каждый ход уменьшается не более чем на 1.
    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      Спасибо. Теперь  понятно количество accepted по этой задаче.
  • 14 лет назад, # ^ |
      Проголосовать: нравится +3 Проголосовать: не нравится

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

    Ну а имея это знание просто ищем самую близкую блоху.

     

14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Кто-нибудь пытался дорешивать задачу D?
Уже почти неделю висит с Check failed, на clar никакого ответа.