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 \nXOR 2 3 \nOR 1 3 \nAND 1 2 \nAND 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;
}

相关文章:

  • 2021-06-28
  • 2021-09-23
  • 2021-08-31
  • 2021-09-01
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-03-08
  • 2022-01-16
  • 2022-12-23
  • 2021-04-30
相关资源
相似解决方案