「雜題亂刷2」CF862D

wangmarui發表於2024-08-29

簡單題。

題目連結

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;
}