简单题。
题目链接
CF862D Mahmoud and Ehab and the binary string
解题思路
首先我们可以发现,字符串的第一个字母不是 \(1\) 就是 \(0\),因此我们可以容易花费 \(2\) 次询问来找到数字 \(0\) 或数字 \(1\) 所在的一个位置。
然后,显然的,我们以先找到的数字为 \(0\) 为例,那么我们就可以先询问一个全为 \(0\) 的字符串,然后通过构造前 \(Mid\) 位为 \(1\),其余都为 \(0\) 的字符串来二分出第一个 \(1\) 的位置,因为你会发现,如果这个字符串与全为 \(0\)
的字符串的权值差为 \(Mid\),那么前 \(Mid\) 为都为 \(0\),反之,前 \(Mid\) 位必然有至少一个 \(1\),因此我们可以通过二分来确定,而先找到的数字为 \(1\) 也是同理。
综上,询问次数为 \(3 + \log n\) 次,可以通过此题。
参考代码
点击查看代码
#include<bits/stdc++.h>
using namespace std;
//#define map unordered_map
#define re register
#define ll long long
#define forl(i,a,b) for(re ll i=a;i<=b;i++)
#define forr(i,a,b) for(re ll i=a;i>=b;i--)
#define mid ((l+r)>>1)
#define lowbit(x) (x&-x)
#define pb push_back
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
//#define endl '\n'
#define QwQ return 0;
ll _t_;
void _clear(){}
ll n;
string ans;
string S;
ll get(string s)
{
ll sum=0;
forl(i,0,n-1)
sum+=s[i]!=ans[i];
return sum;
}
ll ask(string s)
{
cout<<"? "<<s<<endl;
ll x;//=get(s);
cin>>x;
return x;
}
string f(ll x)
{
string SS="";
forl(i,1,x)
SS+='0';
forl(i,x+1,n)
SS+='1';
return SS;
}
string f2(ll x)
{
string SS="";
forl(i,1,x)
SS+='1';
forl(i,x+1,n)
SS+='0';
return SS;
}
ll ans0,ans1;
void solve()
{
_clear();
cin>>n;
forl(i,1,n)
S+='0';
ll q1=ask(S);
S[0]='1';
ll q2=ask(S);
if(q1>q2)
ans1=1;
else
ans0=1;
S="";
forl(i,1,n)
S+='1';
ll q3=ask(S);
if(!ans0)
{
ll L=1,R=n;
while(L<R)
{
ll Mid=(L+R)/2;
if(ask(f(Mid))==q3+Mid)
L=Mid+1;
else
R=Mid;
}
cout<<"! "<<L<<' '<<ans1<<endl;
}
else
{
ll L=1,R=n;
while(L<R)
{
ll Mid=(L+R)/2;
if(ask(f2(Mid))==q1+Mid)
L=Mid+1;
else
R=Mid;
}
cout<<"! "<<ans0<<' '<<L<<endl;
}
}
int main()
{
// IOS;
_t_=1;
// cin>>_t_;
while(_t_--)
solve();
QwQ;
}