题意

题目链接

系统中有两个数\\((a, b)\\),请使用\\(62\\)以内次询问来确定出\\((a, b)\\)

每次可以询问两个数\\((c, d)\\)

\\(a \\oplus c > b \\oplus d\\)返回\\(1\\)

\\(a \\oplus c = b \\oplus d\\)返回\\(0\\)

\\(a \\oplus c < b \\oplus d\\)返回\\(-1\\)

保证/需要保证\\(0 \\leqslant a, b, c, d, < 2^{30}\\)

Sol

严重怀疑自己小学数学没学好,刚开始以为\\(a, b, c, d < 2^{30}\\)说明每位只有两次机会,然后模拟了\\(4 * 4 * 3\\)种情况后发现怎么都搞不了,今天看std发现是每位询问两次后还有额外的两次询问机会qwqqqqq

如果多两次机会的话就能搞了,因为我打比赛的时候遇到的问题就是如何确定出当前两位和除去这两位之后的大小关系。这样我们可以上来先询问出\\((a, b)\\)的大小关系,然后xjb特判一下。。

标算好神仙啊。。

#include<bits/stdc++.h> 
#define Pair pair<int, int>
#define MP(x, y) make_pair(x, y)
#define fi first
#define se second
//#define int long long 
#define LL long long 
#define rg register 
#define pt(x) printf("%d ", x);
#define Fin(x) {freopen(#x".in","r",stdin);}
#define Fout(x) {freopen(#x".out","w",stdout);}
using namespace std;
const int MAXN = 1e6 + 10, INF = 1e9 + 10, mod = 1e9 + 7;
const double eps = 1e-9;
int Query(int c, int d) {
    printf("? %d %d\\n", c, d); fflush(stdout);
    int opt; scanf("%d", &opt); return opt;
}
int a, b, flag, B = 29;
main() {
    flag = Query(0, 0);
    for(int i = B; i >= 0; i--) {
        int x = Query(a | (1 << i), b), y = Query(a, b | (1 << i));
        if(x == y) {
            if(flag == 1) a |= (1 << i);
            else b |= (1 << i); 
            flag = x;
        } else if(x == -1) {
            a |= (1 << i);
            b |= (1 << i);
        }
    }
    printf("! %d %d", a, b);
    return 0;
}
收藏 打印