题目链接
题意
存在两个未知数a,b你可以通过一系列问题(交互,询问不超过62次)求得a,b是什么
询问方式给交互姬,两个整数c,d
a ^ c > b ^ d,交互姬返回1
a ^ c = b ^ d,交互姬返回0
a ^ c < b ^ d,交互姬返回-1
思路
当时想询问62次,a,b二进制才30位,大概可以先确定最高位,每两次询问确定a和b的一位,从高到底可以无影响的判断下去。
大致思路如此,我忽略了。。低位对高位是存在影响(如果当前位a ^ c = b ^ d那么低位会产生影响)
所以我们可以最初先查询?0 0,来判断低位的影响(如何判断下面提)。
每位查询询问两次,?表示低位有影响
对于每位查询 | a=0,b=0 | a=0,b=1 | a=1,b=0 | a=1,b=1 |
---|---|---|---|---|
c=1,d=0,值为flag1 | 1 | ? | ? | -1 |
c=0,d=1,值为flag2 | -1 | ? | ? | 1 |
上表没有突出
1.忽略高位
2.如果(a=0,b=1 )和 (a=1,b=0),那么两次查询结果相同,这里可以想一想。
所以
if(flag1 != flag2)
{
if(flag1 == -1) a = 1, b = 1;
if(flag1 == 1) a = 0, b = 0;
}
对于?即flag1 == flag2 的情况:
我们最先查询? 0 0,用wtf记录返回值。
如果是?说明这位两者当前位不同,两个二进制不同最高位,一定能决定谁大谁小。
所以根据wtf来判断01情况,记得每次这样判断完都要更新wtf,因为要保证比较的是两个二进制不同最高位。
wtf更新为flag1,因为flag1表示了当前位无影响时,低位谁打谁小。
详见代码
代码
#include <stdio.h>
int main()
{
int a = 0, b = 0;
printf("? 0 0\n"); fflush(stdout); int wtf; scanf("%d",&wtf);
for(int i = 29; ~i; --i)
{
printf("? %d %d\n",(1<<i)+a,(0<<i)+b); fflush(stdout); int flag1; scanf("%d",&flag1);
printf("? %d %d\n",(0<<i)+a,(1<<i)+b); fflush(stdout); int flag2; scanf("%d",&flag2);
if(flag1 == flag2)
{
if(wtf == 1) a += (1<<i);
else b += (1<<i);
wtf = flag1;
}
else if(flag1 == -1) a += (1<<i), b += (1<<i);
}
printf("! %d %d\n",a, b);
fflush(stdout);
return 0;
}