1451E2 - Bitwise Queries (Hard Version)(交互,思维,位运算猜数组)

Posted issue是fw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1451E2 - Bitwise Queries (Hard Version)(交互,思维,位运算猜数组)相关的知识,希望对你有一定的参考价值。

LINK

先用 n − 1 n-1 n1次操作得到所有 a i ⊕ a i − 1 a_i\\oplus a_{i-1} aiai1

还剩 3 3 3步可以知晓任意一个数,根据异或的性质就能求出其他所有数

考虑到用两次操作可以得到两数之和

a + b = 2 ∗ ( a & b ) + ( a ⊕ b ) a+b=2*(a\\&b)+(a\\oplus b) a+b=2(a&b)+(ab)

考虑能否得到三数之和,我们考虑先求出三数之和的两倍

2 ∗ ( a + b + c ) = ( a + b ) + ( a + c ) + ( b + c ) 2*(a+b+c)=(a+b)+(a+c)+(b+c) 2(a+b+c)=(a+b)+(a+c)+(b+c)

显然可以用六次操作得到这个,于是就知道了 a , b , c a,b,c a,b,c分别是什么

然且当 a , b , c a,b,c a,b,c分别取 a 1 , a 2 , a 3 a_1,a_2,a_3 a1,a2,a3,异或值是已经知晓的,只需要询问与

这样一来,刚好操作次数是 ( n − 1 ) + 3 = n + 2 (n-1)+3=n+2 (n1)+3=n+2

#include <bits/stdc++.h>
using namespace std;
const int maxn = 3e5+10;
int n,e[maxn],a[maxn];
int OR(int l,int r)
{
	cout << "OR " << l << " " << r << endl;
	int x; cin >> x;
	return x;
}
int XOR(int l,int r)
{
	cout << "XOR " << l << " " << r << endl;
	int x; cin >> x;
	return x;	
}
int AND(int l,int r)
{
	cout << "AND " << l << " " << r << endl;
	int x; cin >> x;
	return x;	
}
int main()
{
	cin >> n;
	for(int i=2;i<=n;i++)	e[i] = XOR(i-1,i);
	int xor_ab = e[2], xor_bc = e[3], xor_ac = e[2]^e[3];
	int and_ab = AND(1,2), and_bc = AND( 2,3 ), and_ac = AND( 1,3 );
	int abc = ( 2*( and_ab+and_bc+and_ac )+xor_ab+xor_bc+xor_ac )/2;
	int bc = 2*and_bc+xor_bc;
	a[1] = abc-bc;
	for(int i=2;i<=n;i++)	
	{
		e[i] ^= e[i-1];
		a[i] = e[i]^a[1];
	}
	cout << "! ";
	for(int i=1;i<=n;i++)	cout << a[i] << " ";
}

然后似乎遇到了瓶颈,因为在hard_version中只允许使用 n + 1 n+1 n+1次操作

上面的解法很难优化,不过还有条件,就是 a i ∈ [ 0 , n − 1 ] & & n < = 2 16 a_i\\in[0,n-1]\\&\\&n<=2^{16} ai[0,n1]&&n<=216(且 n n n一定是 2 2 2的整次幂)

我们先询问所有 a i ⊕ a 1 a_i\\oplus a_1 aia1的值,这样只要没有出现两个值相等的情况或者值为零就没有重复数字

c i = a 1 ⊕ a i c_i=a_1\\oplus a_i ci=a1ai

分情况讨论

①.若所有数字没有重复,那么必然是一个 [ 0 , n − 1 ] [0,n-1] [0,n1]的排列

此时的异或结果必然恰好是落在 [ 0 , n − 1 ] [0,n-1] [0,n1]

那么我们找到 c x = 1 c_x=1 cx=1,说明 a 1 a_1 a1 a x a_x ax只有最低位不同,我们询问一次 A N D \\rm AND AND可以得到除了最低位的答案

我们再找到 c y = n − 2 c_y=n-2 cy=n2,说明 a 1 a_1 a1 a y a_y ay只有最低位相同,我们询问一次 O R \\rm OR OR可以得到最低位的答案

那么 a 1 a_1 a1求出来就做完了,刚好操作 n + 1 n+1 n+1

②.若有重复,又分两种

一是 a 1 = a x a_1=a_x a1=ax,此时有 c x = 0 c_x=0 cx=0,那么询问一次 a 1 o r   a x a_1\\rm or \\ a_x a1or ax即可

二是 a x = a y a_x=a_y ax=ay,此时有 c x = c y c_x=c_y cx=cy,此时询问 a x o r   a y a_x \\rm or\\ a_y axor ay可以得到 a x a_x ax的值

那么就可以得到 a 1 a_1 a1的值

#include <bits/stdc++.h>
using namespace std;
const int maxn = 3e6+10;
int n,e[maxn],a[maxn],vis[maxn];
int OR(int l,int r)
{
	cout << "OR " << l << " " << r << endl;
	int x; cin >> x;
	return x;
}
int XOR(int l,int r)
{
	cout << "XOR " << l << " " << r << endl;
	int x; cin >> x;
	return x;	
}
int AND(int l,int r)
{
	cout << "AND " << l << " " << r << endl;
	int x; cin >> x;
	return x;	
}
int main()
{
	cin >> n;
	for(int i=2;i<=n;i++)	e[i] = XOR以上是关于1451E2 - Bitwise Queries (Hard Version)(交互,思维,位运算猜数组)的主要内容,如果未能解决你的问题,请参考以下文章

Bitwise And Queries

Kattis - bitwise Bitwise (RMQ+尺取+树上dfs)

Python PEG 中 bitwise_or 的目的是啥?

bitwise_and 输入参数的大小不匹配

Python OpenCV —— bitwise

Bitwise Operators