题解:CF2078E Finding OR Sum

题意

这是一道交互题。

SPJ 有两个你初始未知的数 \(x,y\),你可以进行最多两次的询问,每次询问,你向标准输出给出一行一个整数 \(n\),SPJ 从标准输入返回一行一个值代表 \((n \mathbin{|} x) + (n \mathbin{|} y)\)。其中 \(|\) 代表按位或。在进行完至多两次的询问后,你需要向标准输出给出一行一个字符 !,然后 SPJ 会从标准输入返回一行一个值 \(m\),你需要输出 \((m \mathbin{|} x) + (m \mathbin{|} y)\)。有多测。

题解

我们看到两次询问,每次询问都得获得一半的信息。我们考虑第一次询问的值是 0x2AAAAAAA。转换成二进制就是 0b101010...10。我们可以从中获得 \(x\)\(y\) 的第 \(0,2,4...\) 位的信息。由于 0b101010...10 不管按位或 \(x\) 还是 \(y\),或完的结果都是 0b1?1?1?...1?,第 \(1,3,5...\) 位的值都是 \(1\),我们可以减掉 0b101010...10,以获得裸的 \(x,y\) 的偶数位上的信息。而因为返回的答案是 \((n \mathbin{|} x) + (n \mathbin{|} y)\),所以需要减两次。减完的就是只保留了第 \(0,2,4...\) 位的 \(x,y\) 相加。

我们把减完的答案设为 \(a_1\),考虑到如果 \(x,y\) 在该位上的值可能都是 \(1\),从而导致进位,所以我们考虑把在二进制下的 \(a_1\) 两位两位分成一组,第 \(0,1\) 位是一组,第 \(2,3\) 位是一组。我们考虑一组里的两位。很显然只会有三种情况:000110。那么三种情况分别对应 \(x,y\) 在该位都是 \(1\),有一个是 \(1\),两个都是 \(1\)。第二次询问 \(n\)0x15555555,如法炮制,我们就可以获得第 \(1,3,5...\) 位的信息。这样我们就可以求出 \(x,y\) 的具体值。

那有人要问了:有一个是 \(1\) 怎么搞?我又不知道那个是 \(1\)。其实无所谓。我们最终要求的 \((m \mathbin{|} x) + (m \mathbin{|} y)\)。考虑 \(m\) 这位是 \(0\)。那么显然,无论这个 \(1\)\(x\) 或是 \(y\)\(x \mathbin{|} m\)\(y \mathbin{|} m\) 在那一位上的和也还是 \(1\)。对于 \(m\) 那一位是 \(1\),那就更无所谓了,因为无论是啥或上 \(1\) 都是 \(1\)

代码

#include<bits/extc++.h>
#define int long long
using namespace std;
const int q1 = 0x2aaaaaaa,q2 = 0x15555555;
int a1,a2,x,y,m;
void solve()
{
    cout << q1 << endl;
    cin >> a1;
    a1 -= q1 * 2;// 减去询问的 n,得到裸的信息
    cout << q2 << endl;
    cin >> a2;
    a2 -= q2 * 2;
    x = y = 0;// 记得清空
    for (int i = 0; i < 30; i++)
    {
        int tmp = i & 1 ? a2 : a1;
        // 对于奇数位,我们获得的信息是 a1,偶数位就是 a2
        if (tmp & (1 << i))// 如果是 01 的情况
            x |= (1 << i);// 只有一个 1
        else if (tmp & (1 << (i + 1)))// 00 或者 10 时,判断是 00 还是 10
        {// 如果是 10 就是 x,y 都是 1,反之都是 0
            x |= (1 << i);
            y |= (1 << i);
        }
    }
    cout << '!' << endl;
    cin >> m;
    cout << (m | x) + (m | y) << endl;
}
signed main()
{
    int t;
    cin >> t;
    while (t--)
        solve();
    return 0;
}
posted @ 2025-03-11 15:01  伊埃斯  阅读(101)  评论(0)    收藏  举报