D. Ehab and another another xor problem
time limit per test 1 second
memory limit per test 256 megabytes
inputstandard input
outputstandard output
This is an interactive problem!
Ehab plays a game with Laggy. Ehab has 2 hidden integers (a,b). Laggy can ask a pair of integers (c,d) and Ehab will reply with:
1
1
1 if
a
⊕
c
>
b
⊕
d
.
a⊕c>b⊕d.
a⊕c>b⊕d.
0
0
0 if
a
⊕
c
=
b
⊕
d
.
a⊕c=b⊕d.
a⊕c=b⊕d.
−
1
-1
−1 if
a
⊕
c
<
b
⊕
d
.
a⊕c<b⊕d.
a⊕c<b⊕d.
Operation a⊕b is the bitwise-xor operation of two numbers a and b.
Laggy should guess (a,b) with at most 62 questions. You’ll play this game. You’re Laggy and the interactor is Ehab.
It’s guaranteed that 0 ≤ a , b < 2 30 0≤a,b<2^{30} 0≤a,b<230.
Input
See the interaction section.
Output
To print the answer, print “! a b” (without quotes). Don’t forget to flush the output after printing the answer.
Interaction
To ask a question, print “? c d” (without quotes). Both c and d must be non-negative integers less than
2
30
2^{30}
230. Don’t forget to flush the output after printing any question.
After each question, you should read the answer as mentioned in the legend. If the interactor replies with -2, that means you asked more than 62 queries and your program should terminate.
To flush the output, you can use:-
fflush(stdout) in C++.
System.out.flush() in Java.
stdout.flush() in Python.
flush(output) in Pascal.
See the documentation for other languages.
Hacking:
To hack someone, print the 2 space-separated integers a and b ( 0 ≤ a , b < 2 30 ) (0≤a,b<2^{30}) (0≤a,b<230).
Example
inputCopy
1
-1
0
outputCopy
? 2 1
? 1 2
? 2 0
! 3 1
思路:很明显我们需要一位一位的来确定a,b。从高位向低位来确定会简单点,假设a,b的高前几位已经确定好,当前正在确定第k位。有四种情况:
a
[
k
]
=
0
,
b
[
k
]
=
0
;
a[k]=0,b[k]=0;
a[k]=0,b[k]=0;
a
[
k
]
=
0
,
b
[
k
]
=
1
;
a[k]=0,b[k]=1;
a[k]=0,b[k]=1;
a
[
k
]
=
1
,
b
[
k
]
=
0
;
a[k]=1,b[k]=0;
a[k]=1,b[k]=0;
a
[
k
]
=
1
,
b
[
k
]
=
1
;
a[k]=1,b[k]=1;
a[k]=1,b[k]=1;
然后询问
L
=
a
s
k
(
a
∣
(
1
<
<
k
)
,
b
)
;
R
=
a
s
k
(
a
,
b
∣
(
1
<
<
k
)
)
;
L=ask(a|(1<<k),b);R=ask(a,b|(1<<k));
L=ask(a∣(1<<k),b);R=ask(a,b∣(1<<k));
若
a
[
k
]
=
0
,
b
[
k
]
=
0
,
a[k]=0,b[k]=0,
a[k]=0,b[k]=0,则
L
=
1
,
R
=
−
1
;
L=1,R=-1;
L=1,R=−1;
若
a
[
k
]
=
0
,
b
[
k
]
=
1
,
a[k]=0,b[k]=1,
a[k]=0,b[k]=1,则
L
=
R
L=R
L=R,此时要根据a,b低
k
k
k位大小的比较才能确定;
若
a
[
k
]
=
1
,
b
[
k
]
=
0
,
a[k]=1,b[k]=0,
a[k]=1,b[k]=0,则
L
=
R
,
L=R,
L=R,此时要根据a,b低
k
k
k位大小的比较才能确定;
若
a
[
k
]
=
1
,
b
[
k
]
=
1
,
a[k]=1,b[k]=1,
a[k]=1,b[k]=1,则
L
=
−
1
,
R
=
1
;
L=-1,R=1;
L=−1,R=1;
所以当 L = R L=R L=R时,若 a 低 k 位 > b 低 k 位 , a [ k ] = 1 , b [ k ] = 0 a_{低k位}>b_{低k位},a[k]=1,b[k]=0 a低k位>b低k位,a[k]=1,b[k]=0;否则 a [ k ] = 0 , b [ k ] = 1. a[k]=0,b[k]=1. a[k]=0,b[k]=1.
如何确定低 k k k位的大小呢,我们可以一开始就比较出a,b的大小,然后逐步向下推。
#include<bits/stdc++.h>
using namespace std;
const int MAX=1e6+10;
typedef long long ll;
int ask(ll x,ll y)
{
printf("? %lld %lld\n",x,y);
fflush(stdout);
int ans;
scanf("%d",&ans);
return ans;
}
int main()
{
ll a=0,b=0;
int tag=ask(0,0); //确定a,b大小
for(int i=29;i>=0;i--)
{
int L=ask(a^(1ll<<i),b);
int R=ask(a,b^(1ll<<i));
if(L==R)
{
if(tag==-1)b^=1ll<<i;//低i位 a<b
if(tag==1)a^=1ll<<i; //低i位 a>b
tag=L; //递推tag
}
else if(L==-1)
{
a^=1ll<<i;
b^=1ll<<i;
}
}
printf("! %lld %lld\n",a,b);
return 0;
}