@dalbio

Как решить задачу на or?

Дан m-массив целых чисел единственная операция которую можно выполнить это узнать xor 2-х элементов под индексами i,j.Как узнать где находится 0? (гарантируется,что 0 всегда есть).(Если можно то объясните пожалуйста).Заранее спасибо!
Эта задача: https://codeforces.com/contest/1364/problem/E (ну точнее её часть, чтобы восстановить перестановку надо знать где 0),а как найти 0 я не могу понять даже когда прочитал разбор.
Просто понятного объяснения тоже будет достаточно (или где прочитать,чтобы стало понятно как решать).
  • Вопрос задан
  • 229 просмотров
Решения вопроса 3
@Mercury13
Программист на «си с крестами» и не только
Это невозможно.
Пусть у нас есть массив, состоящий НЕ ЦЕЛИКОМ из нулей и содержащий хоть один ноль.
Возьмём любой ненулевой элемент a и про-XOR’им с ним все элементы массива.
Ноль переместился в другое место, а результаты нашей операции a[i] xor a[j] не изменились.
Получается, что первый массив неотличим от второго, и нули в них в разных местах.

Например: массив 0 1 2 3 неотличим от массива 1 0 3 2.
0 xor 1 = 1 … 1 xor 0 = 1
0 xor 2 = 2 … 1 xor 3 = 2
0 xor 3 = 3 … 1 xor 2 = 3
1 xor 2 = 3 … 0 xor 3 = 3
1 xor 3 = 2 … 0 xor 2 = 2
2 xor 3 = 1 … 3 xor 2 = 1
Ну а 0 xor 0, 1 xor 1, 2 xor 2 и 3 xor 3 всегда были нулями.

------------------

В версии с OR — берём a[0] or a[i], поддерживая AND этих сумм и подсчитывая, сколько раз этот самый AND среди наших сумм встречается.
1) Если числа, превышающие AND, встречаются столько раз, сколько [ну, подсчитайте, сколько чисел от 0 до N−1 будут иметь все эти биты] — отбросим наше 0-е число, а также проверенные числа, чья сумма НЕ совпадает с AND, и начнём сначала.
ПРИМЕР: 2 3 4 0 1
2 or 3 = 5, AND=5
2 or 4 = 6, AND=2 — бит 2 тут будут иметь только 2 и 3, отбрасываем 2, 3 и 4.

Если AND встречается 2k−1 раз (k — кол-во битов в AND), оставим ТОЛЬКО ЭТИ случаи и снова начнём сначала.
ПРИМЕР: 2 1 0 3
2 OR 1 = 3, AND=3
2 OR 0 = 2, AND=2
2k−1=1, и нам хватает одной встречи числа 2 — оставляем 2 и 0.

Остались три числа — действуем по стандартному алгоритму.
Осталось одно число — оно 0.
Остались два числа — одно 0, другое некий бит. Мы должны найти число, этого бита не имеющее. Снова проходим по результату предыдущего обхода, суммируя сначала с одним, потом с другим. Видим разницу — понятно, где 0, а где бит.
Ответ написан
Использовать свойство e50acc171007b00d4a1f5f4ce0a9e900c62763d7
Ответ написан
wataru
@wataru Куратор тега Алгоритмы
Разработчик на С++, экс-олимпиадник.
Есть решение, но оно на плохих тестах, если не повезет, не влезет в лимит.
Чтобы вам повезло, можно "перемешать" входные данные случайным образом. Заведите случайную перестановку. Далее внизу я про нее как бы забуду, но когда я говорю спросить про элементы i и j вы должны справшивать про p[i] и p[j]. Как только вы найдете, что 0 в p[k] - про эту случайную перестановку можно забыть и далее использовать элемент p[k] для востановления перестановки.

Спросите про элементы 0 и 1. Запомните a[0] | a[1].

Вот у вас есть 2 элемента каких-то, вы знаете их позиции и a[i]|a[j]. Мы будет добавлять к ним элементы 2..n-1 по одному, все время выбрасывая один или несколько, в которых нуля точно нет.

Вот есть у вас элеметы x, y и вы знаете a=x|y. возьмем новый элемент z и спросим b=y|z.

Мог ли 0 быть в x? тогда бы a = x|y=0|y = y. Т.е. предыдущее значение a должно вкладываться в новое b как множество единиц. Аналогичный критерий для возможности z быть нулем - b вкладывается в a.

Eсть 4 взаимоисключающих варианта, как множества бит a и b соотносятся:
1) a целиком вкладывается в b, или a|b == b, a != b, например 5 вкладывается в 7.
2) b целиком вкладывается в a, или a|b == a, a != b
3) a == b
4) ничего из выше перечисленного, например, 3 и 6.

Мы уже становили, что x может быть 0 только в случаях 1) и 3). z может быть нулем только в случаях 2) и 3).

В каких случаях может быть нулем y? только в 1), 2) и 4)

Теперь алгоритм, если выпал случай 1), то мы выбрасываем z. При этом значение текущего OR уменьшилось как множество.

Если выпал случай 2), то мы выбрасываем x. При этом значение текущего OR уменьшилось как множество.

Если выпал вариант 3), то мы выбрасываем y и нам придется спросить x|z, ведь нам надо знать OR оставшихся элеметов. Это плохо тем, что мы спросили 2 раза, рассморев один новый элемент. В неудачном случае мы бы задали 2n вопросов только ища 0 и у нас не осталось бы квоты на восстановление самой перестановки.

Но тут есть 2 подварианта. 3а) Если значение x|z стало меньше, как множество, то ок. 3б) Но оно еще могло бы остаться таким же, т.е. x|y=y|z=x|z. Но в этом случае, по аналогичным рассуждениям нуля не может быть нигде среди этих трех элементов! А значит мы можем выкинуть и их все, избавившись от двух элементов за два вопроса.

Если выпал вариант 4), то мы выбрасываем x или z.

Таким образом задав от n до 2n (в самом неудачном случае) мы получаем в конце 2 элемента в одном из которых точно 0, а второй - a.

Чтобы восстановить кто из двух оставшихся элементов кто: по ходу отсеивания, задавая любой вопрос запоминайте для какой пары чисел вы видели нулевой бит в каждом разряде. (Т.е. спросили про i|j получили ответ 5. Тут второй бит 0, значит запомнили, что i|j дает 0 в бите 2. И поддерживайте массив для всех разрядов).
Если вам хоть сколько-нибудь повезет. вы наберете достаточно таких примеров.

Теперь пройдитесь по всем примерам, что вы ранее видели и выберите тот, который имел 0 в разряде, где у a стоит 1. пусть это были элементы i и j. Теперь спросите x|i. Если и там этот разряд 0, то x=0, иначе у=0.

Тут почти нарисовался строго убывающий инвариант - размер множетсва бит в OR для текущих кандидатов, но пункт 3б) его ломает, ведь мы получаем 2 новых элемента и множество может стать любым. Но случайный порядок вопросов должен сделать этот вариант маловаероятным. У вас запас примерно 150 впоросов на максимальном тесте. Возможно тут можно придумать какую-то строгую схему, где какой-то инвариант строго убывает на лишних вопросах и может убывать не более 100 раз.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы