CF1292E Rin and The Unknown Flower

Link
首先我们进行(5)次查询:CCCHCOHOOO
这样我们就能够确定序列中((1,n))的所有字符。
同时所有O的前一个字符和所有C的后一个字符都已被确定。
对于位置(1),它有可能是OH
对于位置(n),它有可能是CH
也就是总共只有(4)种可能的情况了。
那么我们再进行(3)次长度为(n)的查询即可。
这样的总代价为(1.25+frac3{n^2}),当(nge5)时可以通过。
然后我们特判(n=4)的情况。
首先我们进行(4)次查询:CCCHCOHO
如果此时位置(2)和位置(3)已经被确定,而位置(1)和位置(4)未被确定.
注意到位置(1)不可能为C,那么总共就只有(6)种可能的情况,再进行(5)次长度为(n)的查询即可,总代价为(1.3125)
如果此时位置(2)和位置(3)未被确定,那么我们再查询OO
这样我们一定能够确定位置(2)和位置(3),并且它要么是OO要么是HH
如果是OO那么位置(1)也被确定了,位置(n)只有(2)种可能的字符,再进行(1)次长度为(n)的查询即可,总代价为(1.3125)
如果是HH那么我们查询一次HHH,这样也能够确定所有的字符了。

#include<cstdio>
#include<cstring>
int read(){int x;scanf("%d",&x);return x;}
int n;char s[60],t[60],c[4]="OHC";
void ask()
{
    printf("? %s
",t+1),fflush(stdout);
    int m=read();
    for(int i=1;i<=m;++i) for(int p=read()-1,j=1;t[j];++j) s[p+j]=t[j];
}
void work1(){for(int i=0;i<2;++i)for(int j=0;j<3;++j)memcpy(t,s,n+1),t[1]=c[i],t[4]=c[j],ask();}
void solve2()
{ 
    for(int i=0;i<3;++i)
	for(int j=0;j<3;++j)
	{
	    if((i==2&&!s[1])||(j==0&&!s[n])||(s[1]&&s[1]^c[i])||(s[n]&&s[n]^c[j])||(!s[1]&&!s[n]&&i==1&&j==2))continue;
	    memcpy(t,s,n+1),t[1]=c[i],t[n]=c[j],ask();
	}
    if(!s[1]&&!s[n]) s[1]='H',s[n]='C';
}
int main()
{
    for(int T=read();T;--T)
    {
	n=read(),memset(s,0,sizeof s),memset(t,0,sizeof t);
	t[1]='C',t[2]='C',ask(),t[1]='C',t[2]='H',ask(),t[1]='C',t[2]='O',ask(),t[1]='H',t[2]='O',ask();
	if(n==4&&!s[1]&&s[2]&&s[3]&&!s[4]) work1();
	else
	{
	    t[1]='O',t[2]='O',ask();
	    for(int i=2;i<n;++i) if(!s[i]) s[i]='H';
	    if(n==4&&!s[1]&&s[2]=='H'&&s[3]=='H'&&!s[4])
	    {
		t[1]='H',t[2]='H',t[3]='H',ask();
		if(!s[1]) s[1]='O';
		if(!s[4]) s[4]='C';
	    }
	    else solve2();
	}
	printf("! %s
",s+1),fflush(stdout),read();
    }
}
原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12295756.html