1. 程式人生 > >Codeforces Round #525 (Div. 2) D. Ehab and another another xor problem(思維)

Codeforces Round #525 (Div. 2) D. 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

input

standard input

output

standard output

This is an interactive problem!

Ehab plays a game with Laggy. Ehab has 2 hidden integers (a,b)(a,b). Laggy can ask a pair of integers (c,d)(c,d) and Ehab will reply with:

  • 1 if a⊕c>b⊕da⊕c>b⊕d.
  • 0 if a⊕c=b⊕da⊕c=b⊕d.
  • -1 if a⊕c<b⊕da⊕c<b⊕d.

Operation a⊕ba⊕b is the bitwise-xor operation of two numbers aa and bb.

Laggy should guess (a,b)(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<2300≤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 cc and dd must be non-negative integers less than 230230. 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 aa and bb (0≤a,b<230)(0≤a,b<230).

Example

input

Copy

1
-1
0

output

Copy

? 2 1
? 1 2
? 2 0
! 3 1

Note

In the sample:

The hidden numbers are a=3a=3 and b=1b=1.

In the first query: 3⊕2=13⊕2=1 and 1⊕1=01⊕1=0, so the answer is 1.

In the second query: 3⊕1=23⊕1=2 and 1⊕2=31⊕2=3, so the answer is -1.

In the third query: 3⊕2=13⊕2=1 and 1⊕0=11⊕0=1, so the answer is 0.

Then, we printed the answer.

題意:又是個互動題,現在你的對手有兩個數字c和d,你每次詢問a,b兩個數,他會告訴你a^c和b^d哪個大,前者大他會給你輸入1,後者大他會給你輸入-1。讓你在62次詢問之內確定c和d的大小,輸出格式見上。

思路:

顯然是兩次詢問確定兩個數二進位制的一位,從而確定這兩個數的二進位制的30位是0還是1。不過我確定沒想到構造方法。賽後看了別人的程式碼。

首先直接詢問0 0,就可以知道a和b的大小。(是否用到先不管,因為我們還是很容易看出這個結論的)

設x=0,y=0。

從最高位開始(因為從最低位無法通過大小確定每一位),分別詢問

c=(x,y|(1<<i))和 d=(x|(1<<i),y)

好好思考一下為什麼要這樣詢問。

如果c==1&&d==-1,那麼顯然a和b的第i位都為1,反之則為0.

否則與從當前位開始a的後i位和b的後i位的大小有關,設為aa和bb

如果aa>bb 則a的第i位為1,b的第i位為0,反之同理。

然後根據c的值更新a和b哪個大哪個小即可。這個時候剛開始的0 0詢問就有用了,再用一個變量表示aa和bb的大小即可。

在紙上畫一畫好好想想。

程式碼:

#include <bits/stdc++.h>
using namespace std;
int go(int a,int b)
{
    cout<<"? "<<a<<" "<<b<<endl;
    int x;
    cin>>x;
    return x;
}
int main()
{
    int x=0,y=0;
    int ac=go(x,y);
    for(int i=29;i>=0;i--)
    {
        int c=go(x,y|(1<<i)),d=go(x|(1<<i),y);
        if(c==1&&d==-1)
        {
            x|=(1<<i);
            y|=(1<<i);
        }
        else if(c==-1&&d==1)
        {
            x=x;
            y=y;
        }
        else
        {
            if(ac==1) x|=(1<<i);
            else y|=(1<<i);
            ac=(c==1);
        }
    }
        cout<<"! "<<x<<" "<<y<<endl;
    return 0;
}