这是一个交互式问题。
有 $n$ 枚硬币排成一行,从左到右编号为 $1$ 到 $n$。其中恰好有 $k$ ($k < n$) 枚硬币是伪币,其余 $(n - k)$ 枚是真币。伪币比真币轻。所有真币的重量相同,而伪币的重量可能不同。已知伪币是连续的,即它们的编号为 $p, p + 1, \dots, (p + k - 1)$。
你需要找到最左侧伪币的编号。你可以使用称重操作,这类似于在双盘天平上称重:选择两组互不相交的硬币,找出哪一组更重,或者两组重量相同。
输入格式
第一行包含三个整数 $n, k, g$ ($1 \le k < n \le 10^4, 0 \le g \le 6$),分别表示硬币总数、伪币数量和测试块编号。
交互
要执行称重请求,请输出 “? $s_1$ $s_2$ $a_1$ $a_2 \dots a_{s_1}$ $b_1$ $b_2 \dots b_{s_2}$”,其中 $s_1$ 和 $s_2$ 分别表示两组被称重硬币的数量,数组 $a$ 和 $b$ 分别表示第一组和第二组硬币的编号。
作为对请求的响应,评测程序将输出一个整数 $x$ ($x \in \{0, 1, 2\}$)。如果 $x = 1$,则第一组比第二组重;如果 $x = 2$,则第二组比第一组重;如果 $x = 0$,则两组重量相同。
如果请求无效(例如,超过了最大请求次数或请求参数无效),评测程序将输出 -1 并终止。在这种情况下,请立即终止你的程序以获得 Wrong Answer 判决。
在输出每一行后,请务必调用 flush 方法。你可以使用:
- C++ 中的
fflush(stdout)、cout << endl或cout.flush(); - Java 中的
System.out.flush(); - Pascal 中的
flush(output); - Python 中的
sys.stdout.flush(); - 其他编程语言请查阅相关文档。
输出格式
输出答案时,请输出一行格式为 “! $p$” 的内容,其中 $p$ ($1 \le p \le n$) 是最左侧伪币的编号。
子任务
设 $q$ 为你在某个测试块中最多可以进行的称重查询次数。
- (5 分): $n \le 16, q = 16$;
- (9 分): $k = 1, q = 16$;
- (7 分): $k = 1, q = 11$;
- (16 分): $k \le 16, q = 11$;
- (9 分): 所有伪币重量相同, $q = 11$;
- (最高 54 分): $q = 300$。设使用的最大称重次数为 $c$。如果 $c \le 9$,你将获得 54 分,否则你将获得 $\lfloor 54 \cdot \max(-0.0004 \cdot c + 0.3134, 0.018 + \frac{9.0773}{c}) \rfloor$ 分。
以下是用于计算最后一个测试块得分的 C++ 代码:
((c <= 9) ? 54 : int(54 * (max((-0.0004 * c + 0.3134), (0.018 + 9.0773 / c)))))
评分表
| $c \le 17$ | 分数 | $18 \le c \le 27$ | 分数 | $28 \le c \le 300$ | 分数 |
|---|---|---|---|---|---|
| $\le 9$ | 54 | 18 | 28 | 28 | 18 |
| 10 | 49 | 19 | 26 | 29-30 | 17 |
| 11 | 45 | 20 | 25 | 31-42 | 16 |
| 12 | 41 | 21 | 24 | 43-89 | 15 |
| 13 | 38 | 22 | 23 | 90-135 | 14 |
| 14 | 35 | 23 | 22 | 136-181 | 13 |
| 15 | 33 | 24 | 21 | 182-227 | 12 |
| 16 | 31 | 25 | 20 | 228-274 | 11 |
| 17 | 29 | 26-27 | 19 | 275-300 | 10 |
样例
输入 1
4 1 0 0 0 2
输出 1
? 1 1 1 2 ? 1 1 2 4 ? 1 1 3 4 ! 3