CF1292E Rin and The Unknown Flower 题解

IO 交互题 fflush(stdout) 害人不浅!!1

注意到如果我们发起询问 CO 就可以花费 2 的代价知道整个串,不过代价过高,所以我们考虑减小点代价。

考虑发起询问 CO,CH,CC,这样我们必然可以知道除了最后一位以外所有 C 的位置,然后类似的询问 HO,OO,这样我们必然可以知道除了第一位以外所有 O 的位置(前面问过一次 CO)。

考虑第二位至第 \(n-1\) 位,注意到此时里面不确定的位置必然都是 H,因为如果有 C 或者 O 肯定已经被问出来了。

这样就只剩下第一位和第 \(n\) 位了,又第一位不会是 C,最后一位不会是 O,于是至多只有 4 种情况,问 3 次即可知道答案。

代价为 \(5\times\dfrac{1}{4}+3\times\dfrac{1}{n^2}\),易知该式在 \(n\ge5\) 时小于等于 1.4。

然后 \(n\ge4\),所以 \(n=4\) 还要另外想办法。下面大分类讨论预警,可以画个决策树理解。

注意到上面问了五个串 CO,CH,CC,HO,OO\(n=4\) 不行的关键在于后面 3 次是错代价过大,然而这些试错是必须的,所以只能减少前面的询问。

考虑先询问 CO,CH,CC,HO,如果我们当前已经问出来了至少两个位置,那么剩下只有至多两个位置不确定且前三位必然不是 C,最坏情况有六种可能,试五次错即可,代价 \(4\times\dfrac{1}{4}+5\times\dfrac{1}{16}=1.3125\)

如果这些都没问出来,那么只有两种可能,一种是含有 OO 一种是含有 HH,然后在决策树上发现这样问完后只需要问一次长度为 4 的串即可,没超 1.4,于是问一下 OO

如果有,说明只可能是 OOOO,OOOH,OOOC,OOHC,OOHH 这四种情况(剩余情况肯定前面都被问出来了),同时已知 OOOO 不用询问,如果有两个位置不确定必是 OOHC,OOHH 中一种,否则是 OOOH,OOOC 中一种,无论哪种代价都是 \(5\times\dfrac{1}{4}+\dfrac{1}{16}=1.3125\)

否则中间两位必然是 HH,第一位只能是 O,H,最后一位只能是 C,H,然而我们不能询问 3 次(否则代价为 \(1.4375\)),于是问一下 HHH,这样可以确定这两位是不是 H,如果不是那也只有一种情况,代价 \(5\times\dfrac{1}{4}+\dfrac{1}{9}\approx1.361<1.4\)

做完了,我写代码的时候 \(n\ge5\) 写了 1k,\(n=4\) 写了 3k /fad

Code:

/*
========= Plozia =========
	Author:Plozia
	Problem:CF1292E Rin and The Unknown Flower
	Date:2022/11/13
========= Plozia =========
*/

#include <bits/stdc++.h>
typedef long long LL;
#define Flu fflush(stdout)
#define rt return

const int MAXN = 50 + 5;
int n;
char str[MAXN], Next[6][2] = {{'H', 'H'}, {'H', 'O'}, {'O', 'H'}, {'O', 'O'}, {'H', 'C'}, {'O', 'C'}};

int Read()
{
	int sum = 0, fh = 1; char ch = getchar();
	for (; ch < '0' || ch > '9'; ch = getchar()) fh -= (ch == '-') << 1;
	for (; ch >= '0' && ch <= '9'; ch = getchar()) sum = (sum << 3) + (sum << 1) + (ch ^ 48);
	rt sum * fh;
}

void Solve2()
{
	puts("? CC"); Flu; int k = Read(), cnt = 0;
	for (int i = 1; i <= k; ++i) { ++cnt; int x = Read(); str[x] = str[x + 1] = 'C'; }
	puts("? CO"); Flu;
	k = Read(); for (int i = 1; i <= k; ++i) { ++cnt; int x = Read(); str[x] = 'C', str[x + 1] = 'O'; }
	puts("? CH"); Flu;
	k = Read(); for (int i = 1; i <= k; ++i) { ++cnt; int x = Read(); str[x] = 'C', str[x + 1] = 'H'; }
	puts("? HO"); Flu;
	k = Read(); for (int i = 1; i <= k; ++i) { ++cnt; int x = Read(); str[x] = 'H', str[x + 1] = 'O'; }
	if (cnt > 0)
	{
		cnt = 0; for (int i = 1; i <= n; ++i) cnt += (str[i] == '?');
		if (cnt == 0) { printf("! %c%c%c%c\n", str[1], str[2], str[3], str[4]); Flu; rt; }
		if (cnt == 1)
		{
			if (str[1] == '?')
			{
				printf("? H%c%c%c\n", str[2], str[3], str[4]); Flu;
				k = Read(); if (k) { Read(); printf("! H%c%c%c\n", str[2], str[3], str[4]); Flu; rt; }
				printf("! O%c%c%c\n", str[2], str[3], str[4]); Flu; rt;
			}
			printf("? %c%c%cH\n", str[1], str[2], str[3]); Flu;
			k = Read(); if (k) { Read(); printf("! %c%c%cH\n", str[1], str[2], str[3]); Flu; rt; }
			printf("? %c%c%cO\n", str[1], str[2], str[3]); Flu;
			k = Read(); if (k) { Read(); printf("! %c%c%cO\n", str[1], str[2], str[3]); Flu; rt; }
			printf("! %c%c%cC\n", str[1], str[2], str[3]); Flu; rt;
		}
		if (str[1] == '?' && str[4] == '?')
		{
			for (int i = 0; i < 5; ++i)
			{
				printf("? %c%c%c%c\n", Next[i][0], str[2], str[3], Next[i][1]); Flu;
				int k = Read(); if (k) { Read(); printf("! %c%c%c%c\n", Next[i][0], str[2], str[3], Next[i][1]); Flu; rt; }
			}
			printf("! O%c%cC\n", str[2], str[3]); Flu; rt;
		}
		if (str[1] == '?')
		{
			for (int i = 0; i < 3; ++i)
			{
				printf("? %c%c%c%c\n", Next[i][0], Next[i][1], str[3], str[4]); Flu;
				int k = Read(); if (k) { Read(); printf("! %c%c%c%c\n", Next[i][0], Next[i][1], str[3], str[4]); Flu; rt; }
			}
			printf("! OO%c%c\n", str[3], str[4]); Flu; rt;
		}
		for (int i = 0; i < 5; ++i)
		{
			printf("? %c%c%c%c\n", str[1], str[2], Next[i][0], Next[i][1]); Flu;
			int k = Read(); if (k) { Read(); printf("! %c%c%c%c\n", str[1], str[2], Next[i][0], Next[i][1]); Flu; rt; }
		}
		printf("! %c%cOC\n", str[1], str[2]); Flu; rt;
	}
	puts("? OO"); Flu; k = Read(); for (int i = 1; i <= k; ++i) { ++cnt; int x = Read(); str[x] = str[x + 1] = 'O'; }
	if (cnt)
	{
		cnt = 0; for (int i = 1; i <= n; ++i) cnt += (str[i] == '?');
		if (cnt == 0) { printf("! %c%c%c%c\n", str[1], str[2], str[3], str[4]); Flu; rt; }
		if (cnt == 1)
		{
			puts("? OOOC"); Flu; int k = Read();
			if (k) { Read(); puts("! OOOC"); Flu; rt; }
			else { puts("! OOOH"); Flu; rt; }
		}
		puts("? OOHC"); Flu; int k = Read(); if (k) { Read(); puts("! OOHC"); Flu; rt; }
		puts("! OOHH"); Flu; rt;
	}
	puts("? HHH"); Flu; k = Read(); for (int i = 1; i <= k; ++i) { int x = Read(); str[x] = str[x + 1] = str[x + 2] = 'H'; }
	printf("! %cHH%c\n", (str[1] == '?') ? 'O' : str[1], (str[4] == '?') ? 'C' : str[4]); Flu; rt; 
}
void Solve()
{
	n = Read(); for (int i = 1; i <= n; ++i) str[i] = '?';
	if (n == 4) { Solve2(); rt; } int k;
	puts("? CO"); Flu; k = Read(); for (int i = 1; i <= k; ++i) { int x = Read(); str[x] = 'C', str[x + 1] = 'O'; }
	puts("? CC"); Flu; k = Read(); for (int i = 1; i <= k; ++i) { int x = Read(); str[x] = str[x + 1] = 'C'; }
	puts("? CH"); Flu; k = Read(); for (int i = 1; i <= k; ++i) { int x = Read(); str[x] = 'C', str[x + 1] = 'H'; }
	puts("? HO"); Flu; k = Read(); for (int i = 1; i <= k; ++i) { int x = Read(); str[x] = 'H', str[x + 1] = 'O'; }
	puts("? OO"); Flu; k = Read(); for (int i = 1; i <= k; ++i) { int x = Read(); str[x] = 'O', str[x + 1] = 'O'; }
	for (int i = 2; i < n; ++i) if (str[i] == '?') str[i] = 'H';
	for (int i = 0; i < 5; ++i)
	{
		if (i == 1 || i == 3) continue ;
		printf("? %c", (str[1] == '?') ? Next[i][0] : str[1]);
		for (int _ = 2; _ < n; ++_) printf("%c", str[_]);
		printf("%c\n", (str[n] == '?') ? Next[i][1] : str[n]); Flu;
		k = Read();
		if (k)
		{
			Read();
			printf("! %c", (str[1] == '?') ? Next[i][0] : str[1]);
			for (int _ = 2; _ < n; ++_) printf("%c", str[_]);
			printf("%c\n", (str[n] == '?') ? Next[i][1] : str[n]); Flu; rt;
		}
	}
	printf("! %c", (str[1] == '?') ? 'O' : str[1]);
	for (int _ = 2; _ < n; ++_) printf("%c", str[_]);
	printf("%c\n", (str[n] == '?') ? 'C' : str[n]); Flu; rt;
}

int main()
{
	int t = Read(); while (t--) { Solve(); if (Read() == 0) rt 0; } rt 0;
}
posted @ 2022-11-14 07:36  Plozia  阅读(28)  评论(0编辑  收藏  举报