题解:P13340 [EGOI 2025] Dark Ride / 黑暗乘车
鲜花
感觉很妙的一道题啊,不过我咋一道青做一天呢?
解法
先思考
再考虑正解。我们思考为啥题目让我们求的是两边的开关。可以发现,如果一次询问中不包含两边的开关,那么它返回的答案一定是连通块数的两倍,是个偶数。如果这个询问包含两个两边的开关,那么答案也是偶数。如果恰好包含一个两端的开关,答案就是奇数。这就体现了两边的开关的特殊性。
于是题目就转化为了:现在有个零一序列(代表原题面中的是否为两端的开关),恰好有两个一,每次你可以查询一个子序列中一的个数的奇偶性,让你求出这两个一的位置。
我们发现有个测试组三。在
通过这个测试组三的提示,我们学会了如何在一个只有一个一的集合中使用
最终交互次数上限是
代码
#include<bits/stdc++.h>
using namespace std;
bool is[16];
int xu[30010];
bool xuan[30010];
int main(){
int n;
cin>>n;
int tot=0;
for(int i=0;i<=14;i++){
int cnt=0;
for(int j=1;j<=n;j++){
if((1<<i)&j)cnt++;
}
if(!cnt)continue;
cout<<"? ";
for(int j=1;j<=n;j++){
if((1<<i)&j){
cout<<"1";
}
else cout<<"0";
}
cout<<endl;
int x;
cin>>x;
if(x%2){
is[i]=1;
if(!tot){
for(int j=1;j<=n;j++){
if((1<<i)&j)xu[++tot]=j;
}
}
}
}
int l=1,r=tot;
while(l<r){
int mid=(l+r)>>1;
cout<<"? ";
for(int i=1;i<=n;i++)xuan[i]=0;
for(int i=l;i<=mid;i++)xuan[xu[i]]=1;
for(int i=1;i<=n;i++){
cout<<xuan[i];
}
cout<<endl;
int x;
cin>>x;
if(x%2){
r=mid;
}
else l=mid+1;
}
l=xu[l];
cout<<"! "<<l-1<<" ";
int sum=l;
for(int i=0;i<=14;i++){
if(is[i]){
sum^=(1<<i);
}
}
cout<<sum-1;
return 0;
}