CF1292E. Rin and The Unknown Flower

题目描述

交互题

有一个长度为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~3)*(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\)可以省掉一次但是没有必要

(UPD:考虑找到的串的位置,如果不在开头则会对前一位产生影响,则上限变成2*3=6种,如果在开头后面则是3*3-4=5种)

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\n");fflush(stdout);
			scanf("%d",&m);fo(i,1,m) scanf("%d",&j),a[j]='C',a[j+1]='C';
			printf("? CH\n");fflush(stdout);
			scanf("%d",&m);fo(i,1,m) scanf("%d",&j),a[j]='C',a[j+1]='H';
			printf("? CO\n");fflush(stdout);
			scanf("%d",&m);fo(i,1,m) scanf("%d",&j),a[j]='C',a[j+1]='O';
			printf("? HO\n");fflush(stdout);
			scanf("%d",&m);fo(i,1,m) scanf("%d",&j),a[j]='H',a[j+1]='O';
			printf("? OH\n");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('\n');
					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\n");fflush(stdout);
			scanf("%d",&m);fo(i,1,m) scanf("%d",&j),a[j]='C',a[j+1]='C';
			printf("? CH\n");fflush(stdout);
			scanf("%d",&m);fo(i,1,m) scanf("%d",&j),a[j]='C',a[j+1]='H';
			printf("? CO\n");fflush(stdout);
			scanf("%d",&m);fo(i,1,m) scanf("%d",&j),a[j]='C',a[j+1]='O';
			printf("? HO\n");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\n");fflush(stdout);
				scanf("%d",&m);fo(i,1,m) scanf("%d",&j),a[j]=a[j+1]=a[j+2]='H';
				printf("? OOO\n");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('\n');
				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('\n');
					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('\n');
								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('\n');
		fflush(stdout);
		
		scanf("%d",&l);
		if (!l) return 0;
	}
}
posted @ 2020-08-12 22:44  gmh77  阅读(106)  评论(0编辑  收藏  举报