题解:CF2077B / CF2078E Finding OR Sum

Foreword

交互题。

Solution

考虑如何只需要两次询问确定每一位。

\(V_1,V_2\) 分别表示偶数位、奇数位全为一时的值,询问这两个值之后记得到的答案为 \(W_1,W_2\),你会发现与 \(x,y\) 按位或之后再减去原来的,也就是 \(W_1 - V_1,W_2 - V_2\) 的这两个值分别代表了 \(x,y\) 在奇数位、偶数位的情况。

我们记 \(k_1 = W_1-V_1,k_2 = W_2-V_2\),将 \(k_1.k_2\) 相邻两位从低位到高位分成一组,显然有 \(01,10,00\) 三种情况,\(00\) 的情况不用考虑,\(10\) 说明 \(x,y\)\(1\) 的这一位上都为 \(1\)\(01\) 说明只有一个在 \(1\) 的这一位上为 \(1\)

Code

#include <bits/stdc++.h>
#define int long long 
using namespace std;
inline int Query (int x) {
    cout << x << endl;
    int tmp; cin >> tmp;
    return tmp - x * 2;
}

inline void Solve() {
    int V1 = 0, V2 = 0;
    for (int i = 0; i < 30; i ++) {
        if (i & 1) {
            V2 |= (1 << i);
        } else {
            V1 |= (1 << i);
        }
    }
    // V1 : 10101010101010101010101010101
    // V2 : 10101010101010101010101010101
    int x = 0, y = 0;
    int v1 = Query (V2), v2 = Query (V1);
    // 找到奇数偶数位的情况

    for (int i = 0; i < 30; i ++) {
        int tmp = ((i & 1) ? v2 : v1);
        if ((tmp >> i) & 1) { // 01
            x |= (1 << i);
        } else if ((tmp >> (i + 1)) & 1) { // 10
            x |= (1 << i), y |= (1 << i);
        } else { // 00
            continue;
        }
    }
    cout << "!" << endl;
    int m; cin >> m;
    cout << (m | x) + (m | y) << endl;
    return;
}
signed main() {
    int Test; 
    cin >> Test;
    while (Test --) Solve();
    return 0;
}
posted @ 2025-03-11 15:45  xAlec  阅读(26)  评论(0)    收藏  举报