[EGOI2025] Dark Ride 题解
提供一种从另一个角度的理解。
考虑一个询问可以包含怎样的信息:对于一次游乐实验,若一个开灯连续段既没有包含第一个位置,也没有包含最后一个位置,那么它的贡献必然是偶数(开始和离开都会有恰好一次尖叫);若包含两个端点中的恰好一个,贡献为奇数;若两个都包含,贡献为偶数。
从部分分“
这启发我们把两个目标开关划分到两个不同的集合中。基于事实“两个数不同,那么这两个数必然存在某个二进制位不同”:考虑对于每个位拿出编号满足当前位为
拆位询问和二分各需要
代码非常好写。放代码:
#include<bits/stdc++.h>
using namespace std;
int main(){
ios::sync_with_stdio(false);
int n; cin>>n;
int k=__lg(n)+(__builtin_popcount(n)>1),c=0;
for(int i=0;i<k;i++){
cout<<"? ";
for(int j=0;j<n;j++)
cout<<(j>>i&1);
cout<<endl;
int x; cin>>x,c|=(x&1)<<i;
} // 拆位询问,求异或和
int b=__builtin_ctz(c);
vector<int> v;
for(int i=0;i<n;i++)
if(i>>b&1)v.emplace_back(i);
int l=0,r=v.size()-1;
while(l<r){
int m=l+r>>1;
vector<int> b(n);
for(int i=l;i<=m;i++)
b[v[i]]=1;
cout<<"? ";
for(int i:b)cout<<i;
cout<<endl;
int x; cin>>x;
x&1?(r=m):(l=m+1);
} // 二分过程
cout<<"! "<<v[r]<<' '<<(v[r]^c)<<endl;
return 0;
}