题意
交互题,要猜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;
}