AGC044D Guess the Password 题解
题目链接:AGC044D - Guess the Password
首先我们想先知道整个字符串的长度,发现你可以问长为 $ \text{128} $ 的同一个字符的字符串,这样可以问出每个字符在字符串中出现了多少次,然后我们想把两个已知是圆字符串的子序列的字符串合并是容易的,类似归并排序一样做就可以做到 $ O(|\sum |+Llog|\sum|) $ 次操作。
代码:
#include<bits/stdc++.h>
#define pb push_back
using namespace std;
int ask(string &s)
{
cout<<"? "<<s<<endl;
int x;
cin>>x;
return x;
}
int len;
string merge(string a,string b)
{
if(!a.size())return b;
if(!b.size())return a;
string c="";
for(int i=0,j=0;i<a.size()||j<b.size();)
{
if(i==a.size())c+=b[j++];
else if(j==b.size())c+=a[i++];
else
{
string tmp=c+a[i]+b.substr(j);
if(ask(tmp)==len-tmp.size())c+=a[i++];
else c+=b[j++];
}
}
return c;
}
string solve(vector<string> vc)
{
if(vc.size()==1)return vc[0];
vector<string> vcl,vcr;
for(int i=0;i<vc.size()/2;i++)
{
vcl.pb(vc[i]);
}
for(int i=vc.size()/2;i<vc.size();i++)
{
vcr.pb(vc[i]);
}
return merge(solve(vcl),solve(vcr));
}
signed main()
{
vector<char> ch;
for(int i='a';i<='z';i++)
{
ch.pb(i);
}
for(int i='A';i<='Z';i++)
{
ch.pb(i);
}
for(int i='0';i<='9';i++)
{
ch.pb(i);
}
vector<string> vc;
for(auto x:ch)
{
string s="";
for(int i=1;i<=128;i++)
{
s+=x;
}
int cur=128-ask(s);
len+=cur;
s="";
for(int i=1;i<=cur;i++)
{
s+=x;
}
vc.pb(s);
}
string ans=solve(vc);
cout<<"! "<<ans<<endl;
}

浙公网安备 33010602011771号