Codeforces-1088D:Ehab and another another xor problem(思维)

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. ac>bd.
0 0 0 if a ⊕ c = b ⊕ d . a⊕c=b⊕d. ac=bd.
− 1 -1 1 if a ⊕ c &lt; b ⊕ d . a⊕c&lt;b⊕d. ac<bd.
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 &lt; 2 30 0≤a,b&lt;2^{30} 0a,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 &lt; 2 30 ) (0≤a,b&lt;2^{30}) (0a,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]=0b[k]=0
a [ k ] = 0 , b [ k ] = 1 ; a[k]=0,b[k]=1; a[k]=0b[k]=1
a [ k ] = 1 , b [ k ] = 0 ; a[k]=1,b[k]=0; a[k]=1b[k]=0
a [ k ] = 1 , b [ k ] = 1 ; a[k]=1,b[k]=1; a[k]=1b[k]=1
然后询问 L = a s k ( a ∣ ( 1 &lt; &lt; k ) , b ) ; R = a s k ( a , b ∣ ( 1 &lt; &lt; k ) ) ; L=ask(a|(1&lt;&lt;k),b);R=ask(a,b|(1&lt;&lt;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]=0b[k]=0 L = 1 , R = − 1 ; L=1,R=-1; L=1R=1
a [ k ] = 0 , b [ k ] = 1 , a[k]=0,b[k]=1, a[k]=0b[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]=1b[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]=1b[k]=1 L = − 1 , R = 1 ; L=-1,R=1; L=1R=1

所以当 L = R L=R L=R时,若 a 低 k 位 &gt; b 低 k 位 , a [ k ] = 1 , b [ k ] = 0 a_{低k位}&gt;b_{低k位},a[k]=1,b[k]=0 ak>bka[k]=1b[k]=0;否则 a [ k ] = 0 , b [ k ] = 1. a[k]=0,b[k]=1. a[k]=0b[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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值