【题解】CF2246E

0:总览

我们注意到,只要知道 \(v\) 中某个二进制位的值即可求解

那么如何通过第一次询问求出 \(v\) 中某个二进制位的值呢?

这次询问其实分为两步,第一步是根据回答判断符号,第二步是根据符号中某个二进制位的值

1:推导符号

要判断符号,有一个直观的想法是钦定 \(x=1\)

如果 \(r\) 存在高位 \(1\),则为 | \((r>1)\)

如果 \(r\) 最低位为 \(0\),则为 & \((r=0)\)

否则我们无法判断符号,似乎无计可解,但我们尝试继续深入

2:由符号求值,并求解(已知值,则求解显然)

2.1 \(r=0\)

运算符一定为 &

\(v\) 的最低位为 \(0\)

钦定 \(m_0=0,m_1=1\)

2.2 \(r>1\)

运算符一定为 |

那么我们可以确定 \(v\) 任何 \([1,30]\) 位的值

钦定 \(m_0=0,m_1=2^q\)

2.3 \(r=1\)

2.3.1

此时我们无法确定运算符,故而我们无法确定 \(v\) 某一二进制位的值

单靠 \(d\) 是无法求解的,我们能不能使用 \(m_0\)\(m_1\) 来判断?

如果是 | ,此时 \(r \in \{ m_0,m_1 \}\)

如果是 $,此时大概率 \(r \notin \{m_0,m_1\} (m_0 \oplus v \neq m_1)\)

2.3.2

综合 | 和 & 的两种情况,我们尝试反推,如果 \(r \in \{m_0,m_1\}\),则大概率为 |,启发随机化

我们可不可以同时处理这两种情况?

那么我们可以随机 \(m_0\)\(m_1\) 的值,使得 \(m_0\) 是偶数,\(m_1\) 是奇数

得到 \(r\)

如果 \(r \in \{m_0,m_1\}\),那么 \(v=0\),则看和 \(m_1,m_2\) 哪个相等

否则 \(v\) 的最低位一定是 \(1\),判断 \(r\) 最低位 奇偶 即可

3:代码

#include<bits/stdc++.h>
using namespace std;
mt19937 rnd(time(0));
void solve(){
	cout<<1<<endl;
	int o;cin>>o;
	if(o==0){//0
		cout<<0<<" "<<1<<endl;
		int x;cin>>x;
		if(x%2==0) cout<<0<<endl;
		else cout<<1<<endl;
	}
	else if(o>1){//1
		int val=0;
		for(int i=31;i>=0;i--){
			if(o>>i&1){
				val=1<<i;
				break;
			}
		}
		int m0=0,m1=val;
		cout<<m0<<" "<<m1<<endl;
		int x;cin>>x;
		if(x&val) cout<<0<<endl;
		else cout<<1<<endl;
	}
	else{
		int m0=rnd()%(1<<30)+1,m1=rnd()%(1<<30)+1;
		if(m0&1) m0--;
		if(m1%2==0) m1++;
		cout<<m0<<" "<<m1<<endl;
		int r;cin>>r;
		if(r==m0||r==m1){
			if(r==m0) cout<<0<<endl;
			else cout<<1<<endl; 
		}
		else{
			if(r&1) cout<<0<<endl;
			else cout<<1<<endl;
		}
	}
}
int main(){
	int t;cin>>t;
	while(t--) solve();
	return 0;
}

4:反思

4.1

渐进推导

posted @ 2026-07-14 20:21  Aistyr  阅读(8)  评论(0)    收藏  举报