peiwenjun's blog 没有知识的荒原

CF1292E Rin and The Unknown Flower 题解

题目描述

这是一道交互题。

\(T\) 组数据,交互库有一个长为 \(n\) 的字符串 \(s\) ,字符集为 C,H,O

每次你可以给交互库传送一个字符串 \(t\) ,交互库会返回 \(t\)\(s\) 中出现的所有位置。

具体的,记 \(|t|=m\) ,则 \(a\) 被返回当且仅当 \(s_{a,a+m-1}=t\) ,并且这次交互的代价为 \(\frac1{m^2}\)

要求总代价 \(\le\frac 75\) ,求字符串 \(s\)

数据范围

  • \(1\le T\le 500,4\le n\le 50\)

时间限制 \(\texttt{2s}\) ,空间限制 \(\texttt{256MB}\)

分析

基本思路为,求出 CH 的所有出现位置,其余为 O

直接询问 C 代价过高,考虑询问 CC,CH,CO ,这样可以在 \(\frac 34\) 的代价内获得除 \(s_n\) 外所有 C 的位置。

类似的,询问 CH,HH,OH 即可获得除 \(s_1\) 外的所有 H 的位置,注意 CH 已经问过了。

于是除了 \(s_1\)\(s_n\) ,所有位置已经可以唯一确定。

如果 \(s_1,s_n\) 尚未确定,那么 \(s_1\in\{\texttt H,\texttt O\},s_n\in\{\texttt C,\texttt O\}\) 仅有 \(4\) 种情况。

逐一尝试可以做到在 \(\frac 54+\frac 3{n^2}\) 的代价内求出 \(s\)

还可以继续优化,先求 \(s_1\) 再求 \(s_n\) 即可做到总代价 \(\frac54+\frac1{(n-1)^2}+\frac1{n^2}\)

\(n\ge 5\) 时,总代价不超过 \(1.3525\) ,符合要求。

于是我们只需要单独处理 \(n=4\) 的情况。


然而这才是本题难点。

先询问 CC,CH,CO,HO

  • 如果有收获,那么至多还有两位没有确定,并且仅有 \(s_4\) 可能为 C

    因此至多有 \(2\times 3=6\) 种可能情况,逐一询问代价为 \(\frac 44+\frac 5{16}=1.0625\)

  • 如果没有收获,仅有 HHHC,HHHH,OHHC,OHHH,OOHH,OOHC,OOOC,OOOH,OOOO\(9\) 种可能情况。

    先询问 HHH,OOO ,这样候选集合大小不超过 \(3\) ,逐一询问代价为 \(\frac 44+\frac 29+\frac 2{16}\approx 1.3472\)

综上我们用不超过 \(1.3525\) 的总代价解决了此题。

#include<bits/stdc++.h>
using namespace std;
string s;
char ch[3]={'C','H','O'};
inline int read()
{
    int q=0;char ch=getchar();
    while(!isdigit(ch)) ch=getchar();
    while(isdigit(ch)) q=10*q+ch-'0',ch=getchar();
    return q;
}
vector<int> query(string s)
{
    cout<<"? "<<s<<endl;
    static vector<int> vec;
    vec.resize(read());
    for(auto &p:vec) p=read()-1;
    return vec;
}
void work(string t)
{
    for(auto p:query(t)) for(int i=0;i<t.size();i++) s[p+i]=t[i];
}
string check(string s1,string s2,string s3)
{
    if(query(s1).size()) return s1;
    if(query(s2).size()) return s2;
    return s3;
}
string solve(int n)
{
    s.resize(n);
    for(int i=0;i<n;i++) s[i]='?';
    if(n>=5)
    {
        work("CC"),work("CH"),work("CO"),work("HH"),work("OH");
        for(int i=1;i<=n-2;i++) if(s[i]=='?') s[i]='O';
        work('H'+s.substr(1,n-2));
        if(s[0]=='?') s[0]='O';
        work(s.substr(0,n-1)+'C');
        if(s[n-1]=='?') s[n-1]='O';
        return s;
    }
    work("CC"),work("CH"),work("CO"),work("HO");
    if(count(s.begin(),s.end(),'?')<=2)
    {
        string t="    ";
        vector<string> vec;
        for(int a=0;a<=2;a++)
            for(int b=0;b<=2;b++)
                for(int c=0;c<=2;c++)
                    for(int d=0;d<=2;d++)
                    {
                        t[0]=ch[a],t[1]=ch[b],t[2]=ch[c],t[3]=ch[d];
                        int flg=1;
                        for(int i=0;i<4;i++) flg&=s[i]==t[i]||(s[i]=='?'&&(i==3||t[i]!='C'));
                        if(flg) vec.push_back(t);
                    }
        for(auto t:vec) if(t==vec.back()||query(t).size()) return t;
    }
    if(query("HHH").size()) return check("HHHC","HHHH","OHHH");
    if(query("OOO").size()) return check("OOOC","OOOH","OOOO");
    return check("OHHC","OOHH","OOHC");
}
int main()
{
    for(int t=read();t--;)
    {
        string s=solve(read());
        cout<<"! "<<s<<endl,assert(read());
    }
    return 0;
}

posted on 2023-05-31 17:28  peiwenjun  阅读(7)  评论(0)    收藏  举报

导航