题意:有两数a,b,每次你可以给定c,d询问a xor c和b xor d的大小关系,最多询问62次($a,b<=2^{30}$),问a和b
考虑从高位往低位做,正在做第i位,已经知道了a和b的前i-1位
这样的话,只要让a、c,b、d的前i-1位相同,就和前i-1位没关系了
考虑在第i位上abcd的情况对应的回答(后面的位数都给0),其中~表示与第i位后面的相关
那我可以分别用01 10询问两次,如果是先大后小或是先小后大,就能判断出是00或者11
但如果前后两次相同,那就有可能是01或者10
考虑上一次两次相同的时候是在第j位,具体到底是大于还是小于
然后又因为j+1~i-1位它们a和b都是相同的,所以这个大于还是小于就取决于第i位,所以能得出是01还是10
如果这是第一次相同,那直接再拿00询问一次就可以得到答案
一共61次
1 #include<bits/stdc++.h> 2 #define pa pair<int,int> 3 #define CLR(a,x) memset(a,x,sizeof(a)) 4 #define MP make_pair 5 using namespace std; 6 typedef long long ll; 7 const int maxn=1; 8 9 inline char gc(){ 10 return getchar(); 11 static const int maxs=1<<16;static char buf[maxs],*p1=buf,*p2=buf; 12 return p1==p2&&(p2=(p1=buf)+fread(buf,1,maxs,stdin),p1==p2)?EOF:*p1++; 13 } 14 inline ll rd(){ 15 ll x=0;char c=gc();bool neg=0; 16 while(c<'0'||c>'9'){if(c=='-') neg=1;c=gc();} 17 while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+c-'0',c=gc(); 18 return neg?(~x+1):x; 19 } 20 21 inline int get(int c,int d){ 22 printf("? %d %d ",c,d); 23 fflush(stdout); 24 return rd(); 25 } 26 27 int main(){ 28 //freopen("","r",stdin); 29 int i; 30 int cp=0,dp=0; 31 int a=0,b=0; 32 int lst=0; 33 for(i=29;i>=0;i--){ 34 int v1=get(cp,dp|(1<<i)),v2=get(cp|(1<<i),dp); 35 if(v1==v2){ 36 if(lst==1) a|=(1<<i); 37 else if(lst==-1) b|=(1<<i); 38 else{ 39 if(get(cp,dp)==1) a|=(1<<i); 40 else b|=(1<<i); 41 } 42 lst=v1; 43 }else if(v1==1) a|=(1<<i),b|=(1<<i); 44 cp=a,dp=b; 45 } 46 printf("! %d %d ",a,b); 47 fflush(stdout); 48 return 0; 49 50 }