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

Автор Obk, история, 8 лет назад, По-русски

Пусть нам дан массив int a[n] . И требуется найти все коэффициенты многочлена (x+a[0])*...*(x+a[n-1]) Если считать в лоб, то будет сложность O(n^2). Есть ли способы считать быстрее? Есть ли смысл здесь применять быстрое преобразование Фурье? И есть ли другие хорошие подходы в этом случае. UPD. Как обычно считаю, что все операции производятся по модулю большого числа, если это здесь вдруг имеет значение.

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

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

Автокомментарий: текст был обновлен пользователем Obk (предыдущая версия, новая версия, сравнить).

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

Как раз Фурье это и надо делать. Можно решать за .

Изначально у нас есть n многочленов размера 1, нужно посчитать их произведение. Повторим n - 1 раз такую процедуру: возьмём два многочлена минимальной степени и перемножим с помощью FFT. Утверждается, что это будет работать именно за .

Можно ещё воспринимать это как умножение а-ля дерево отрезков: построим дерево отрезков на n вершинах, где в листьях будут исходные многочлены, а во внутренних вершинах -- произведение многочленов в детях. По факту это то же самое, что и абзацем выше, но так будет проще понять, откуда берётся асимптотика.

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

    Мне понравилось первое утверждение и я решил его доказать. Для простоты будет доказываться следующее эквивалентное утверждение: есть k множеств из попарно различных элементов, общее число элементов n. На каждом шаге мы берём два наименьших множества и меняем на их объединение. Утверждается, что каждое множество будет использовано не более, чем в объединений.

    Рассмотрим последнее объединение. Меньшее множество, очевидно, имеет размер меньше . Большее множество либо было в наборе изначально, тогда мы вызываемся на подзадачу размера , либо было получено на предыдущем шаге, при этом из множеств, которые не превосходят по размеру меньшее множество. Во втором случае первое множество имеет размер от до (иначе мы бы не смогли получить второе множество, чтобы в совокупности у первого и второго было n элементов), значит, мы вызываемся на две подзадачи размера . Отсюда очевидно, что высота любого листа в получившемся дереве не превосходит .

    А попроще кто-нибудь умеет?

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

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

      Ты же пытаешься "для простоты" :) доказать более сложную оценку на максимальную длину кодового слова в кодировании Хаффмана. Там всё не так просто, но тоже можно дать точную оценку в зависимости от минимальной из вероятностей символов (в твоих терминах — O(min|Ai| / n), можно провести похожее рассуждение, но более аккуратное: http://www.work.caltech.edu/pub/Abu-Mostafa2000Huffman.pdf

      Асимптотически точная оценка выглядит как .

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

        Ну здесь ведь вероятности не одинаковы... В случае множеств это не проблема, можно их разложить на единичные и заново собрать. С числами так уже не прокатит. Или я что-то упускаю?

        P.S. А точная оценка — это, конечно, круто. Я так понимаю, тут вообще суммарное количество операций на это дело будет минимальным по всем возможным путям слияния по два множества?

  • »
    »
    8 лет назад, # ^ |
      Проголосовать: нравится +21 Проголосовать: не нравится
    1. Burunduk1 на сборах говорил, что Карацуба в данном случае лучше, потому что лишнего логарифма не будет.
    2. Это задача из контеста, который сейчас идет.
    3. Я поверил Серёже и написал туда Карацубу, хоть и считаюсь (заслуженно) ярым фанатом FFT. В общем, либо я не умею в Карацубу, либо FFT волшебно.
    • »
      »
      »
      8 лет назад, # ^ |
        Проголосовать: нравится +8 Проголосовать: не нравится

      Ну, человек тут спрашивает общеизвестную вещь все-таки. Я тут уже много раз в комментариях писал — если кто-то дал задачу, которая очевидным образом сводится к чему-то очень баянистому, то он сам себе дурак.

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

        Я только сейчас случайно обратил внимание на автора задачи, из-за которой этот вопрос возник, и понял, что это ты и есть :) Задача 10/10 :thumbup:

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

      Про то, что это задача из ongoing контеста, я совершенно согласен с adamant: слишком уж общая задача.

      А как в Карацубе избавиться от логарифма? Нам же от детей нужно не просто произведение в них, но ещё и какие-то перекрёстные произведения.

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

        Никак не надо избавляться, его там просто нет. Разделяй-и-властвуй с пересчетом за O(nc) при c > 1 работает за O(nc).

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

      Это задача из контеста, который сейчас идет.

      Т.к. контест уже закончился, можно свободно его обсуждать. Я спрашивал для этой задачи: https://www.hackerrank.com/contests/w23/challenges/sasha-and-swaps-ii Кто считает, что мой вопрос очень близко к задаче и я поступил не спортивно — пусть бросит в меня камень. Um_nik, можешь показать свое решение через Карацубу?

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

        Могу, но оно не заходит (и вообще работает медленно). Впрочем, я ни разу не сдавал Карацубу куда-либо, так что я не уверен, что это действительно правильно написанная Карацуба.

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

        Я взял это FFT из этого обсуждения, и ещё сначала группирую многочлены по 1000 и каждую группу умножаю без FFT. У меня 10^5 решает за 1.5 сек. Submission