【Codeforces 1292E】Rin and The Unknown Flower

构造,分类讨论。

题目大意:

交互题。

给定一个只由 CHO 组成的字符串 $s$,你可以进行询问,每次给定一个字符串 $t$,会返回 $t$ 在 $s$ 中作为子串出现的所有位置(开头位置),并花费 $\frac 1{|t|^2}$ 的代价。

你需要花费不超过 $\frac 7 5$ 的代价求出 $s$。

保证 $4\leq |s|\leq 50$。

题解:

我们发现,询问 AAABAC 就可以知道位置 $1\sim n-1$ 中的所有 A

相应的,询问 ABBBCB 就可以知道位置 $2\sim n$ 中的所有 B

共用一次询问 AB,这里只需要花费 $\frac 5 4$ 的代价。

此时 $2\sim n-1$ 位置的 AB 确定,剩下的就是 C 了。

还有位置 $1$ 和 $n$。

如果位置 $1$ 没有确定,则不可能是 A。同理位置 $n$ 没有确定,则不可能是 B

那么我们用一次 $n-1$ 的询问和一次 $n$ 的询问即可确定 $1$ 和 $n$ 位置的字符。

总花费 $\frac 5 4+\frac 1{(n-1)^2}+\frac 1 {n^2}$。

当 $n\geq 5$ 时是不会超过的,但是在 $n=4$ 时会超过。

我们可以特判 $n=4$ 的情况,具体实现是一个大分类讨论,可以参考代码。

Code:

#include<iostream>
#include<string>
#include<cstring>
using namespace std;
int T,n;
char ans[55];
bool ask(string s){
    cout<<"? "<<s<<endl;
    int k,x;bool ok;
    for(cin>>k,ok=k;k--;){
        cin>>x;
        for(int i=0;i<s.length();++i)ans[x+i-1]=s[i];
    }
    return ok;
}
int main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    cin>>T;
    while(T--){
        cin>>n;
        memset(ans,0,sizeof ans),ask("CC"),ask("CH"),ask("CO");
        if(n==4){
            if(ans[3]){
                if(!ans[1]){
                    ask("HC");
                    if(!ans[1])ans[1]='O';
                }
                if(!ans[0]){
                    ask((string)"H"+ans[1]);
                    if(!ans[0])ans[0]='O';
                }
            }else if(!ans[0]&&!ans[1]&&!ans[2]){
                if(ask("HO")){
                    if(ans[2]=='H'&&ans[3]=='O'){
                        if(!ans[0]||!ans[1]){
                            ask("HHHO"),ask("OOHO");
                            if(!ans[0]&&!ans[1])ans[0]='O',ans[1]='H';
                        }
                    }else if(ans[1]=='H'&&ans[2]=='O'){
                        ask("HHOH"),ask("HHOO"),ask("HHOC"),
                        ask("OHOH"),ask("OHOO");if(!ans[3])ans[0]='O',ans[3]='C';
                    }else{
                        ask("HOHC"),ask("HOOC"),ask("HOOH"),ask("HOHH");
                        if(!ans[3])ans[2]=ans[3]='O';
                    }
                }else if(ask("OO")){
                    if(!ans[2])ans[2]='H';
                    if(!ans[3])ans[3]=ask((string)"OO"+ans[2]+"H")?'H':'C';
                }else{
                    ask("HHH"),ans[1]=ans[2]='H';
                    if(!*ans)*ans='O';if(!ans[3])ans[3]='C';
                }
            }else{
                if(!ans[0]){
                    ask("HC");if(!ans[0])ans[0]='O';
                }else if(!ans[2]){
                    ask(ans[1]+(string)"H");if(!ans[2])ans[2]='O';
                }
                if(!ans[3]){
                    string s;s=s+ans[0]+ans[1]+ans[2];
                    ask(s+(string)"C");
                    ask(s+(string)"H");
                    if(!ans[3])ans[3]='O';
                }
            }
        }else{
            ask("HH"),ask("OH");
            for(int i=1;i<n-1;++i)if(!ans[i])ans[i]='O';
            if(!ans[n-1]){
                string s;
                for(int i=1;i<n-1;++i)s+=ans[i];
                s+='C';
                ask(s);
                if(!ans[n-1])ans[n-1]='O';
            }
            if(!ans[0]){
                string s;
                for(int i=1;i<n;++i)s+=ans[i];
                s='H'+s;
                ask(s);
                if(!ans[0])ans[0]='O';
            }
        }
        cout<<"! "<<ans<<endl;
        cin>>n;
        if(!n)break;
    }
    return 0;
}