交互题,系统有两个整数 ,你每次可以询问一组整数 ,系统会回答:
- 如果
- 如果
- 如果
其中操作 表示 和 按位异或。
你需要在询问不超过 次之后输出 的值,保证 。
首先显然可以询问一次得到 的大小关系 ,接下来分类讨论:
-
若 ,那么 和 相等,从高位向低位依次枚举,显然第 位为 当且仅当 。这样就可以用 次询问确定 和 ;
-
若 ,那么从高位向低位依次枚举。枚举到第 位时设当前(确定了前面的位的)答案为 和 , 和 的大小关系为 。
显然刚开始 。
枚举到第 位时,询问 和 的大小关系,即询问两个数第 位和更低位都异或上 的大小关系。设询问的结果为 ,分类讨论:
- 若 ,那么 和 的第 位相等,这时若 那么 和 的第 位为 ,因为 和 的最高位都是第 位,这一位均为 那么异或 相当于消去最高位,显然会变得比另一个小;
- 若 ,那么 和 的第 位不相等,这时若 那么 的第 位为 ,否则 的第 位为 。更新完 和 之后再问一次 和 的大小关系来更新 ,注意若此时 更新成 那么剩下的位就要按照 情况的方法处理。
代码如下:
// Problem: CF1088D Ehab and another another xor problem // Contest: Luogu // URL: https://www.luogu.com.cn/problem/CF1088D // Memory Limit: 250 MB // Time Limit: 1000 ms // // Powered by CP Editor (https://cpeditor.org) #include <iostream> #include <cstdio> using namespace std; const int N=29; int a,b; inline int que(int c,int d) { printf("? %d %d\n",c,d); fflush(stdout); int x; scanf("%d",&x); return x; } int main() { int f=que(0,0); int srt=N; if(f!=0) { for(int i=N;i>=0;i--) { int val=1<<i; int pre=que(a^val,b^val); if(pre!=f) { if(f==1) a|=val; else b|=val; f=que(a,b); if(f==0) { srt=i-1; break; } } else if((f==1&&que(a^val,b)==-1)||(f==-1&&que(a,b^val)==1)) a|=val,b|=val; } } for(int i=srt;i>=0;i--) { int val=1<<i; if(que(a,b^val)==1) a|=val,b|=val; } printf("! %d %d\n",a,b); fflush(stdout); return 0; }