题目描述
交互题
有一个长度为n的由C,H,O组成的字符串S,每次可以询问一个串T,返回询问串在S中的位置,一次询问的代价是1/(|T|^2),在总代价<=7/5的代价下找出串S
4<=n<=50
题解
非常有趣的题目,虽然没什么人切+及其难调+题解辣鸡
不是题解做法因为根本没看,以下把CHO对应ABC
n>=5
首先这个代价就很神必,显然不可能询问所有的排列,也不可能询问单个字符
仔细想一下,串太长没有卵用,太短代价太大,所以应该是在2和3最好
一开始想的是询问AA,BB,CC以及ABC的排列,发现代价超了并且好像找不出来
xjb思考后考虑询问AA,AB,AC,BC,CB,这样可以得到部分串并且使A可以几乎全部找出来
如果串中间(非头尾)存在一块未知部分,如果是A一定会被找出来,假设前面的那个是B也不可能是C,所以一定和前面第一个已知的相同
于是可以确定串中间的东西,剩下一个前缀以及最后一位不确定
前缀只可能是BC,最后一位要么是A要么和n-1位相同,所以一共有四种
判断其中三种即可,次数是(5*(1/4)+3*(1/n^2)),当n>=5时可以解决
n=4
考虑n=4的情况,上面的做法仍可以借鉴
先询问AA,AB,AC,BC(没有CB),如果什么都没有找出来就是 一段C+一段B(+A) 的串,因为询问的串一定不会在未知部分出现
那么就有(C0~4)*(A or B)+CCCC共9种,用BBB干掉BBBB,BBBA,CBBB,用CCC干掉CCCA,CCCB,CCCC,剩下三个串用两次询问解决
次数是(4*(1/4)+2*(1/9)+2*(1/16)=1.3472<7/5)
如果第一步找出了东西,那么最多剩下两个位置,手玩一下发现最多有6种情况,暴力判断即可,次数是(4*(1/4)+6*(1/16)=1.375),可以省掉一次但是没有必要
code
3.8K的交互构造题
#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define ll long long
using namespace std;
const char b[3]={'C','H','O'};
int T,n,m,i,j,k,l,tot;
char a[51],A[51],c1,c2;
bool bz;
bool pd(char a,char b) {return !(a=='C' && b=='C' || a=='C' && b=='H' || a=='C' && b=='O' || a=='H' && b=='O');}
int main()
{
scanf("%d",&T);
for (;T;--T)
{
scanf("%d",&n);
memset(a,' ',sizeof(a));
if (n>4)
{
printf("? CC
");fflush(stdout);
scanf("%d",&m);fo(i,1,m) scanf("%d",&j),a[j]='C',a[j+1]='C';
printf("? CH
");fflush(stdout);
scanf("%d",&m);fo(i,1,m) scanf("%d",&j),a[j]='C',a[j+1]='H';
printf("? CO
");fflush(stdout);
scanf("%d",&m);fo(i,1,m) scanf("%d",&j),a[j]='C',a[j+1]='O';
printf("? HO
");fflush(stdout);
scanf("%d",&m);fo(i,1,m) scanf("%d",&j),a[j]='H',a[j+1]='O';
printf("? OH
");fflush(stdout);
scanf("%d",&m);fo(i,1,m) scanf("%d",&j),a[j]='O',a[j+1]='H';
fo(i,2,n-1) if (a[i]==' ' && (a[i-1]=='H' || a[i-1]=='O')) a[i]=a[i-1];
c1=a[1],c2=a[n];tot=bz=0;
fo(i,0,2)
if (c1==' ' && b[i]!='C' || b[i]==c1)
{
memcpy(A,a,sizeof(a));
fo(k,1,n-1) if (a[k]==' ') A[k]=b[i];
fo(j,0,2)
if (c2==' ' && (b[j]==A[n-1] || b[j]=='C') || b[j]==c2)
{
++tot;if (tot==4) break;
printf("? ");
A[n]=b[j];
fo(k,1,n) putchar(A[k]);
putchar('
');
fflush(stdout);
scanf("%d",&m);
if (m) {scanf("%d",&k); memcpy(a,A,sizeof(a));bz=1;break;}
}
if (bz || tot==4) break;
}
if (tot==4) {fo(i,1,n) a[i]=(a[i]==' ')?'O':a[i];a[n]=a[n-1];}
}
else
{
printf("? CC
");fflush(stdout);
scanf("%d",&m);fo(i,1,m) scanf("%d",&j),a[j]='C',a[j+1]='C';
printf("? CH
");fflush(stdout);
scanf("%d",&m);fo(i,1,m) scanf("%d",&j),a[j]='C',a[j+1]='H';
printf("? CO
");fflush(stdout);
scanf("%d",&m);fo(i,1,m) scanf("%d",&j),a[j]='C',a[j+1]='O';
printf("? HO
");fflush(stdout);
scanf("%d",&m);fo(i,1,m) scanf("%d",&j),a[j]='H',a[j+1]='O';
fo(i,2,n-1) if (a[i]==' ' && a[i-1]=='H') a[i]=a[i-1];
if (a[1]==' ' && a[2]==' ' && a[3]==' ' && a[4]==' ')
{
printf("? HHH
");fflush(stdout);
scanf("%d",&m);fo(i,1,m) scanf("%d",&j),a[j]=a[j+1]=a[j+2]='H';
printf("? OOO
");fflush(stdout);
scanf("%d",&m);fo(i,1,m) scanf("%d",&j),a[j]=a[j+1]=a[j+2]='O';
fo(i,2,n-1) if (a[i]==' ' && a[i-1]=='H') a[i]=a[i-1];
}
if (a[1]==' ' && a[2]==' ' && a[3]==' ' && a[4]==' ')
{
a[1]='O';a[2]='H';a[3]='H';a[4]='C';
printf("? ");
fo(i,1,n) putchar(a[i]);putchar('
');
fflush(stdout);
scanf("%d",&m);
if (m) scanf("%d",&k);
else
{
a[1]='O';a[2]='O';a[3]='H';a[4]='H';
printf("? ");
fo(i,1,n) putchar(a[i]);putchar('
');
fflush(stdout);
scanf("%d",&m);
if (m) scanf("%d",&k);
else
a[1]='O',a[2]='O',a[3]='H',a[4]='C';
}
}
else
{
bz=0;
fo(i,0,2)
if (a[1]==' ' || a[1]==b[i])
{
fo(j,0,2)
if ((a[2]==' ' || a[2]==b[j]) && (a[1]!=' ' && a[2]!=' ' || pd(b[i],b[j])))
{
fo(k,0,2)
if ((a[3]==' ' || a[3]==b[k]) && (a[2]!=' ' && a[3]!=' ' || pd(b[j],b[k])))
{
fo(l,0,2)
if ((a[4]==' ' || a[4]==b[l]) && (a[3]!=' ' && a[4]!=' ' || pd(b[k],b[l])))
{
printf("? %c%c%c%c",b[i],b[j],b[k],b[l]);putchar('
');
fflush(stdout);
scanf("%d",&m);
if (m) {a[1]=b[i],a[2]=b[j],a[3]=b[k],a[4]=b[l];scanf("%d",&k);bz=1;break;}
}
if (bz) break;
}
if (bz) break;
}
if (bz) break;
}
}
}
printf("! ");
fo(i,1,n) putchar(a[i]);putchar('
');
fflush(stdout);
scanf("%d",&l);
if (!l) return 0;
}
}