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(互動題之猜數)

題意

互動題,要猜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;
}