Description
交互题,用不超过 (n+2) 次操作猜出一个长度为 (n) 的数组,每次可以指定两个不同的下标,询问这两个位置的数的 AND 或 OR 或 XOR。
Solution
一个直观的思路是先猜出一小部分数,进而通过异或操作得出剩下的。
猜一个是不行的,猜两个似乎也是不行的。
考虑猜三个,我们可以用五个“方程”去求解前三个数,至于选取怎样的组合有很多种方案,可以写个暴力程序尝试几次或者手玩一下。
#include <bits/stdc++.h>
using namespace std;
void clamp(int &x)
{
x = x != 0;
}
bool check(int a, int b, int c, int u, int v, int x, int y, int z)
{
clamp(a);
clamp(b);
clamp(c);
clamp(u);
clamp(v);
clamp(x);
clamp(y);
clamp(z);
return u == (a ^ b) && v == (b ^ c) && x == (a | c) && y == (a & b) && z == (b & c);
}
void solve(int &a, int &b, int &c, int u, int v, int x, int y, int z, int bm)
{
for (int ia = 0; ia < 2; ia++)
{
for (int ib = 0; ib < 2; ib++)
{
for (int ic = 0; ic < 2; ic++)
{
if (check(ia, ib, ic, (u & bm) > 0, (v & bm) > 0, (x & bm) > 0, (y & bm) > 0, (z & bm) > 0))
{
a += bm * ia;
b += bm * ib;
c += bm * ic;
return;
}
}
}
}
}
int main()
{
int u = 0, v = 0, x = 0, y = 0, z = 0, n;
cin >> n;
cout << "XOR 1 2
XOR 2 3
OR 1 3
AND 1 2
AND 2 3"
<< endl;
cout.flush();
cin >> u >> v >> x >> y >> z;
int *a = new int[n + 5];
for (int i = 1; i <= 3; i++)
a[i] = 0;
for (int i = 1; i < n; i *= 2)
solve(a[1], a[2], a[3], u, v, x, y, z, i);
for (int i = 4; i <= n; i++)
{
cout << "XOR 1 " << i << endl;
cout.flush();
cin >> a[i];
a[i] ^= a[1];
}
cout << "! ";
for (int i = 1; i <= n; i++)
cout << a[i] << " ";
cout << endl;
}