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

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

Я временно перестал участвовать в соревнованиях по "личным обстоятельствам", но продолжаю урывками прорешивать задачки на разных сайтах. Напоролся на задачку (точнее мой генератор случайных чисел напоролся на задачку) 8843 Complete the Set.

Честно говоря ничего в голову не приходит — судя по параметрам задачи — 1100 случаев в одном тесте, 65536 чисел в одном сете — полный перебор вряд ли пройдёт, я имею в виду каждое число с каждым пробовать по OR и AND пока не перестанут появляться новые числа. (хотя бы понятно, что в такой ситуации не надо пробовать что-то большее, чем пары чисел — уже прогресс от "absolute brute force").

Но в голове вертится одна из недавних задачек с Topcoder, где нужно было смешивать краски с помощью XOR и решалась она элегантно гауссовой элиминацией — может быть и здесь какая-нибудь хитрость?

Задачка не очень порешенная, "запылившаяся", решило её меньше 50 человек и разборов в интернете я не нашёл. Если знаете как решать, подскажите только идею — в какую сторону копать.

Большое спасибо!

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

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

Это очень медленное решение, но оно получило AC (за 1.01 секунды).

Пусть побитовый XOR это , OR — , AND — .

Пусть n — количество чисел в тесте, k — разрядность (в условии k = 16)

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

Пусть у нас есть несколько ненулевых чисел a1, a2, ..., an. Пусть Пусть . Тогда ответ для a1, ..., an, очевидно, равен ответу для b1, ..., bn. Перейдём к задаче для b1, ..., bn ()

Сгенерируем (например, за , возможно, можно и быстрее) следующие маски mask1, ..., maskk: в maski j - тый бит равен 1, если при всех k от 1 до n в числах bk либо установлен j-тый бит, либо не установлен i-тый; иначе этот бит равен 0.

Фактически мы сделали следующее. Пусть Si — множество чисел q от 1 до n, что в bq i-бит равен 1. Тогда для каждого i мы выделили те j, что .

Теперь пусть . Будем проверять то, лежит ли число v в нашем множестве так:

1) (), то есть v — подмаска M.

2) Пусть С всех maski для таких i, что i-тый бит v равен 1. Тогда надо, чтобы , то есть С подмаска v. ().

Теперь просто проверим все числа за . Итоговая асимптотика равна на тест.

Я хотел бы ещё написать, почему это работает, но этот комментарий уже слишком длинный (а объяснение ещё раза в два длиннее). Поэтому это я сделаю в следующем комментарии.

UPD. Перебор в конце можно делать рекурсивно, немного улучшив асимптотику и время работы.

UPD 2. maski есть просто AND всех чисел b, у которых i-тый бит равен 1, то есть маски можно посчитать за . Итого (в совокупности с UPD 1) можно добиться асимптотики на тест.

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

    Спасибо большое — в следующий свободный час буду разбираться. В том числе, почему работает. Борьба с задачей впечатляет (смотрю по submissions участника по имени Владислав, видимо вы). Финальное время, насколько вижу, 0.69, и оно на уровне лучших решений. Так что, видимо, так оно и должно решаться.

    Потом они ещё это дело гоняют на Pentium III cluster, так что на Codeforces или любом другом сайте оно бы работало быстрее.