CF1617D2 Too Many Impostors (hard version)
题目描述
这是一个交互题。简单版和困难版的唯一区别在于提问次数的限制。
有 $n$ 个玩家,编号从 $1$ 到 $n$。保证 $n$ 是 $3$ 的倍数。
其中有 $k$ 个“impostor”,其余 $n-k$ 个是“crewmate”。“impostor”的数量 $k$ 未知。保证 $\frac{n}{3} < k < \frac{2n}{3}$。
每次提问时,你可以选择三个不同的整数 $a$、$b$、$c$($1 \le a, b, c \le n$),并询问:“在编号为 $a$、$b$、$c$ 的玩家中,impostor 的数量是否多于 crewmate?”如果 impostor 多于 crewmate,返回整数 $0$,否则返回 $1$。
你需要在最多 $n+6$ 次提问内,找出 impostor 的数量 $k$ 以及所有 impostor 的编号。
评测器是自适应的,也就是说 impostor 的编号可能不是预先固定的,可以根据你的提问动态决定。保证在任何时刻,你的所有提问结果都能对应至少一组满足条件的 impostor 分布。
输入格式
每个测试点包含多组测试数据。第一行包含一个整数 $t$($1 \le t \le 100$),表示测试数据组数。
每组测试数据的第一行包含一个整数 $n$($6 \le n < 10^4$,$n$ 是 $3$ 的倍数),表示玩家数量。
保证所有测试数据中 $n$ 的总和不超过 $2 \times 10^4$。
输出格式
对于每组测试数据,交互从读取 $n$ 开始。
然后你最多可以进行 $n+6$ 次提问,格式如下:
`? a b c`($1 \le a, b, c \le n$,且 $a$、$b$、$c$ 两两不同)。
每次提问后,你需要读取一个整数 $r$,如果在 $a$、$b$、$c$ 中 impostor 数量多于 crewmate,则 $r=0$,否则 $r=1$。
如果你收到 $-1$,说明你的提问不合法,请立即退出,否则会收到 Wrong answer 判定。否则你可以继续,因为你的程序会继续从关闭的流中读取数据。
当你确定所有 impostor 的编号后,输出一行:
`! k x_1 x_2 \ldots x_k`
其中 $k$ 是 impostor 的数量,$x_1, x_2, \ldots, x_k$ 是所有 impostor 的编号。请注意,所有内容必须在同一行输出。
输出后,你的程序应继续解决剩余的测试数据,或在全部测试数据解决后退出。
每次输出后请记得换行并刷新输出缓冲区,否则会收到 Idleness limit exceeded 判定。刷新方法如下:
- C++:fflush(stdout) 或 cout.flush()
- Java:System.out.flush()
- Pascal:flush(output)
- Python:stdout.flush()
- 其它语言请查阅相关文档。
说明/提示
示例交互说明(仅用于演示交互过程,不提供解题思路):
对于第一组测试数据:
提问 `? 1 2 3` 返回 $0$,说明 $1$、$2$、$3$ 中 impostor 多于 crewmate。
提问 `? 3 4 5` 返回 $1$,说明 $3$、$4$、$5$ 中 crewmate 多于 impostor。
输出 `! 3 4 1 2`,表示找到了所有 impostor,数量为 $k=3$,编号为 $4$、$1$、$2$。
对于第二组测试数据:
提问 `? 7 1 9` 返回 $1$,说明 $7$、$1$、$9$ 中 crewmate 多于 impostor。
输出 `! 4 2 3 6 8`,表示找到了所有 impostor,数量为 $k=4$,编号为 $2$、$3$、$6$、$8$。
由 ChatGPT 4.1 翻译