深更半夜,突然想到交互题,以前总是放着,从没有做出来过,也没有试图理解过。
今晚突然来了性质。上次打CF掉分了,就是因为一个交互题,完全没有看懂,今晚就来搞搞。。
题目:http://codeforces.com/contest/1088/problem/D
题意:
有一对数a,b。E知道,每次你举两个数c,d。E告诉你与的相对大小,>返回1,=返回0,<返回-1.
请你询问至多62次,根据E的回答,得出确定的a,b
思路:
交互题会根据你的代码给出输入,此题就例如,对于每个样例的a,b,对于你每次询问的c,d,告诉你对应的答案,最后你求出的a,b是正确的,输入会根据你的询问而改变(我是这样理解的,确实跟平时做的题不一样,样例都不方便跑。)
这个题也是挺有趣的,拆成二进制进行求解。(当然我是看了题解的,才理解的。)
递推思想,从影响力最大的最左边一位1<<30,开始考虑。依次考虑到低位。确定出ab
若按二进制,若a=1xxxx b=0yyyy(ab首位异号)
则10000a=0xxxx 00000b=0yyyy
00000a=1xxxx 10000b=1yyyy
两组的答案是一样的,都是xxxx与yyyy的相对大小。即0000xxxx与0000yyyy的对比答案,可以在后边ab异号时做判断。。
所以若00000a > 00000b,则a=1xxxx,b=0yyyy
否则,a=0xxxx,b=1yyyy
若a=1xxxx b=1yyyy(ab首位同号,首位为0同)
10000a=0xxxx < 00000b=1yyyy
00000a=1xxxx > 10000b=0yyyy
两组答案一定是不一样,且若第一组<,则ab首位都是1,若第一组>,则ab首位都为0.
代码:
#include <bits/stdc++.h>
int Q(int x,int y){
printf("? %d %d\n",x,y);
fflush(stdout);
std::cin>>x;
return x;
}
int32_t main(){
int a=0,b=0,t=Q(0,0),x,y,i=1<<30;
//t==1,则a>b,即二进制,a的首位为1的比b的首位为1的靠左。
while(i>>=1){
x=Q(a|i,b); y=Q(a,b|i);
if(x==y)//右边第i+1位异号,大小由右边i位决定。
{
if(t>0) a|=i;
else b|=i;
t=x;//若x>1,右边i位中,左边第一位异号的是a为1,b为0.与一开始的Q(0,0),同理,即此情况下,x==(a=a%i,b=b%i情况下的Q(0,0))
}
else if(x==-1)
{
a|=i,b|=i;
}
}
printf("! %d %d\n",a,b);
}