[CF1451E2] Bitwise Queries (Hard Version) - 交互,位运算
Description
一个隐藏的长度为 \(n\) 的整数数组 \(a\),想让 Ashish 去猜,注意 \(n\) 是 \(2\) 的整数次幂。三种不同类型的查询。它们分别是:
AND \(i\) \(j\): 求元素 \(a_i\) 和 \(a_j\) 每一位的 and (\(1≤i\),\(j≤n\),\(i≠j\))
OR \(i\) \(j\): 求元素 \(a_i\) 和 \(a_j\) 每一位的 or (\(1≤i\),\(j≤n\),\(i≠j\))
XOR \(i\) \(j\): 求元素 \(a_i\) 和 \(a_j\) 每一位的 xor (\(1≤i\),\(j≤n\),\(i≠j\))
Solution
用 n-1 次操作,计算出 \(b_i = a_i \oplus a_1, i \ge 2\),现在只要求出 \(a_1\)
如果原数组中有重复,那么要么一定存在一个 \(b_i = 0\),我们计算 \(a_i \And a_1\) 就得到了 \(a_1\);要么一定存在两个相同的 \(b_i\),这种情况类似
否则,一定存在一个 \(b_i=1, b_j=n-2\),可以分别得出 \(a_1\) 的前 \(15\) 位和最后一位,也就得到了 \(a_1\)
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e6 + 5;
int n, a[N], b[N];
signed main()
{
ios::sync_with_stdio(false);
cin >> n;
int flag = 0, p_1 = 1, p_2 = 1, same_flag = 0, same_a, same_b;
map<int, int> mp;
for (int i = 2; i <= n; i++)
{
cout << "XOR " << 1 << " " << i << endl;
cout.flush();
cin >> b[i];
if (mp[b[i]])
{
same_flag = 1;
same_a = mp[b[i]];
same_b = i;
}
mp[b[i]] = i;
if (b[i] == 0)
flag = i;
if (b[i] == 1)
p_1 = i;
if (b[i] == n - 2)
p_2 = i;
}
if (flag)
{
cout << "AND " << 1 << " " << flag << endl;
cout.flush();
cin >> a[1];
for (int i = 2; i <= n; i++)
a[i] = b[i] ^ a[1];
cout << "! ";
for (int i = 1; i <= n; i++)
cout << a[i] << " ";
cout << endl;
}
else if (same_flag)
{
cout << "AND " << same_a << " " << same_b << endl;
cout.flush();
cin >> a[same_a];
a[1] = a[same_a] ^ b[same_a];
for (int i = 2; i <= n; i++)
a[i] = b[i] ^ a[1];
cout << "! ";
for (int i = 1; i <= n; i++)
cout << a[i] << " ";
cout << endl;
}
else
{
cout << "AND " << 1 << " " << p_1 << endl;
cout.flush();
int t1, t2;
cin >> t1;
cout << "AND " << 1 << " " << p_2 << endl;
cout.flush();
cin >> t2;
a[1] = ((t1 >> 1) << 1) | (t2 & 1);
for (int i = 2; i <= n; i++)
a[i] = b[i] ^ a[1];
cout << "! ";
for (int i = 1; i <= n; i++)
cout << a[i] << " ";
cout << endl;
}
}