Codeforces Round #525 (Div. 2)D. Ehab and another another xor problem

D. Ehab and another another xor problem

题目链接https://codeforces.com/contest/1088/problem/D

Description:

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 ac>bd.
  • 0 if ac=bd.
  • -1 if ac<b⊕d.

Operation ab is the bitwise-xor operation of two numbers aa and bb.

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 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 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 b(0a,b<230)(0≤a,b<230).

 

题意:

交互式题目。有两个隐藏的数a,b,每次可以给出询问"? c d",然后返回:

1.若a^c>b^d,返回1;

2.若a^c=b^d,返回0;

3.若a^c<b^d,返回-1。

然后最多进行62次操作,最终问a,b是多少?

 

题解:

我的第一道交互式题目~这题还是挺有意思的。

a,b最多小于2^30,并且操作次数最多62次,我们可以想到一位一位来分析。

然后模拟一下:

 

当a,b二进制中目前位置都为1时,分别异或1,0和0,1,那么肯定返回的是-1,1;

当a,b二进制中目前位置都为0时,分别异或1,0和0,1,返回的是1,-1;

当a,b二进制中目前位置不同时,异或1,0和0,1的结果是相同的,但正负并不一定。

 

我们现在主要考虑二进制中目前位置不同的情况,这种较为复杂,假设我们已知a>b,那么最高位不同时,肯定a的最高位是1,b的相同位置是0。

那么问题转化为了如何找a,b大小。

我们知道一开始的时候都异或0,0可以轻松地比较出a,b的大小,在之后第一次碰到不相同的情况(询问结果返回的值相同),可以确定;如果还能碰到第二次,那么就可以根据上一次的询问结果来判断大小(在第一次中异或后a,b的最高位变为相同的了,它会返回一个比较值,这个比较值就是后面二进制位数相比较的大小)。

每次找最高位,把当前位置之前的给异或掉就行了。

 

代码如下:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;

int query(int a,int b){
    printf("? %d %d\n",a,b);
    fflush(stdout);
    int tmp;
    scanf("%d",&tmp);
    return tmp;
}

int main(){
    int a=0,b=0;
    int big = query(a,b);
    for(int i=29;i>=0;i--){
        int x=query(a^(1<<i),b),y=query(a,b^(1<<i));
        if(x==y){
            if(big>0) a^=(1<<i);
            else b^=(1<<i);
            big=(x==1);
        }else{
            if(x==-1) a^=(1<<i),b^=(1<<i);
        }
    }
    printf("! %d %d",a,b);
    return 0;
}

 

posted @ 2018-12-06 21:49  heyuhhh  阅读(267)  评论(0编辑  收藏  举报