Codeforces Round #525 (Div. 2) D - Ehab and another another xor problem(交互题之猜数)

题意

交互题,要猜a和b,你输入c和d,

记e=a异或c,f=b异或d

e>f返回1,e==f返回0,e<f返回-1

给你最多62次机会,要求猜出a和b

思路来源

https://blog.csdn.net/weixin_43790474/article/details/84815383

傅老师%%%

题解

(c,d)代表读入了(? c d)

询问(now1,now2),初始now1=0,now2=0;

将结果读入op,op维护从第i位起两数的大小关系

一、op=0,说明自第i位起,后续都相同

那么每次只需区分00还是11即可,

询问(now1^(1<<i),now2),左大则为00,右大则为11

二、op≠0,只能为00,01,10,11中的一种(第i位的a与第i位的b)

将第i位同时取反,即询问(now1^(1<<i),now2^(1<<i)),记为op1

(1)op=1,不可能为01

①op1=1,不可能为10,只能为00,11

询问(now1^(1<<i),now2),为1则为00,为-1则为11

②op1=1,只能为10,此时去掉这一位,大小关系可能反转,

故令now1,now2更新后,再询问op

(2)op=-1,不可能为10

①op1=-1,不可能为01,只能为00,11

询问(now1^(1<<i),now2),为1则为00,为-1则为11

②op1=1,只能为01,此时去掉这一位,大小关系可能反转,

故令now1,now2更新后,再询问op

由于初始会询问一次op确定大小关系,

30位每一位最多询问两次,最后!输出,恰62次。

心得

交互题特点:每次输出完之后及时fflush(stdout),printf与scanf互换

这题半夜做出来可能性还是不大的,好好补就是了

交互题其实挺有意思的,只是被虐的挺惨……

见过三四道了……上次华师大那个就没补GG

一早起来发现C被n==1情况hack掉了心情复杂

代码

#include <iostream>
#include <algorithm> 
#include <cstring>
#include <cstdio>
#include <cmath>
#include <set>
#include <map>
#include <vector>
#include <stack>
#include <queue>
#include <functional>
const int INF=0x3f3f3f3f;
const int maxn=2e4+10; 
const int mod=1e9+7;
const int MOD=998244353;
const double eps=1e-7;
typedef long long ll;
#define vi vector<int> 
#define si set<int>
#define pii pair<int,int> 
#define pi acos(-1.0)
#define pb push_back
#define mp make_pair
#define lowbit(x) (x&(-x))
#define sci(x) scanf("%d",&(x))
#define scll(x) scanf("%lld",&(x))
#define sclf(x) scanf("%lf",&(x))
#define pri(x) printf("%d",(x))
#define rep(i,j,k) for(int i=j;i<=k;++i)
#define per(i,j,k) for(int i=j;i>=k;--i)
#define mem(a,b) memset(a,b,sizeof(a)) 
using namespace std;
int a[50],b[50],op,now1,now2;
void check(int pos)
{
	int tmp=1<<pos,op1,op2;
	if(op==0)
	{
		printf("? %d %d\n",now1^tmp,now2);//判断00 11 
		fflush(stdout);
		scanf("%d",&op1);
		if(op1==1)a[pos]=b[pos]=0;
		else a[pos]=b[pos]=1;
		now1^=(a[pos]<<pos);now2^=(b[pos]<<pos);
		return;
	}
	printf("? %d %d\n",now1^tmp,now2^tmp);//00 01 10 11
	fflush(stdout);
	scanf("%d",&op1);
	if(op==1)//不可能是01 
	{
		if(op1==1)//不可能是10
		{
		printf("? %d %d\n",now1^tmp,now2);//00 11
	        fflush(stdout);
	        scanf("%d",&op2);
	        if(op2==-1)a[pos]=b[pos]=1;
	        else a[pos]=b[pos]=0;
	        now1^=(a[pos]<<pos);now2^=(b[pos]<<pos);
		} 
		else//本大于,因最高位而翻转
		{
                a[pos]=1,b[pos]=0;
	        now1^=(a[pos]<<pos);now2^=(b[pos]<<pos);
	        printf("? %d %d\n",now1,now2);
	        fflush(stdout);
	        scanf("%d",&op);
		} 
	}
	else//不可能是10 
	{
		if(op1==-1)//不可能是01 
		{
		printf("? %d %d\n",now1^tmp,now2);//00 11
	        fflush(stdout);
	        scanf("%d",&op2);
	        if(op2==1)a[pos]=b[pos]=0;
	        else a[pos]=b[pos]=1;
	        now1^=(a[pos]<<pos);now2^=(b[pos]<<pos);
		}
		else
		{
			a[pos]=0,b[pos]=1;
			now1^=(a[pos]<<pos);now2^=(b[pos]<<pos);
			printf("? %d %d\n",now1,now2);
			fflush(stdout);
	                scanf("%d",&op);
		} 
	}
}
int main()
{ 
   printf("? %d %d\n",now1,now2);
   fflush(stdout);
   scanf("%d",&op);
   for(int i=29;i>=0;--i)
   {
   	check(i);
   }
   printf("! %d %d\n",now1,now2);
   fflush(stdout);
   return 0;
}

猜你喜欢

转载自blog.csdn.net/Code92007/article/details/84830114
今日推荐