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){//0cout<<0<<" "<<1<<endl;int x;cin>>x;if(x%2==0) cout<<0<<endl;else cout<<1<<endl;}else if(o>1){//1int 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;
}
