P11984 [JOIST 2025] 占卜 3 / Fortune Telling 3

题目背景

请使用 C++ 20 提交。不要引入 `anna.h` 和 `bruno.h`,并在代码头加入以下语句: ```cpp int DrawCard(int); ```

题目描述

**这是一道通信题。交互库是非自适应的。** Anna 和 Bruno 在玩一种用卡牌进行的占卜游戏 $Q$ 次,规则如下。 1. 有许多上面写着 $0$ 或 $1$ 的卡牌叠成一堆。Anna 从牌堆中一次抽出 $N$ ($=900$) 张卡牌。Anna 和 Bruno 知道 $N$ 的值。 2. 每次抽到卡牌时,她会决定是弃掉这张牌还是将其放到桌上。 - 如果她选择将牌放到桌上,她会把这张牌插入桌上的卡牌序列中。 - 形式化地,当桌上有 $l$ 张卡牌时,她选定非负整数 $x$($0 \leq x \leq l$),并将这张牌放在桌上从左数第 $x$ 张卡牌右侧。 - 当 $x = 0$ 时,她将这张牌放在桌上卡牌序列的最左侧。 3. 当 Anna 抽完并处理完 $N$ 张卡牌后,她的操作结束。**占卜结果**是这 $N$ 张卡牌中上面写着数字 $1$ 的卡牌数量。 4. 当 Anna 结束操作后,Bruno 会看到桌上的卡牌序列。基于这些信息,他需要猜出占卜结果。 如果 Bruno 猜对了,占卜就算成功。 当桌上的卡牌越少时,占卜被认为越高明。 请编写一个程序,实现 Anna 和 Bruno 的策略,使得全部 $Q$ 次占卜都成功。 在本题中,Anna 放在桌上的卡牌越少,得分越高。 ### 实现细节 你不应该,也不需要实现 `main` 函数。 在洛谷上评测时,你只需要提交一个文件。 对于 Anna 的策略,你应该实现以下的函数: ```cpp void Anna(int N); ``` 该函数将被调用 $Q$ 次。第 $i$ 次调用表示第 $i$ 次占卜的过程。 参数 `N`($N=900$)代表卡牌的数量。 每次占卜,该函数必须调用以下的函数 $(N+1)$ 次: ```cpp int DrawCard(int x); ``` 使用此函数,Anna 从牌堆中抽卡,并选择丢弃或放置在桌面上。她通过第 $j$ 次调用($1 \leq j \leq N$)的返回值获取第 $j$ 张卡片上的数字。她通过第 $k$ 次调用($2 \leq k \leq N + 1$)的参数指定对第 $(k - 1)$ 张卡片的操作。 - 第 $j$ 次调用($1 \leq j \leq N$)的返回值为 $0$ 或 $1$,表示第 $j$ 张卡片上的数字。 - 特别地,第 $(N + 1)$ 次调用的返回值为 $-1$,表示 Anna 已完成抽卡。 - 第 $1$ 次调用的参数 $x$ 必须为 $-1$,否则程序将被判定为 $\texttt{Wrong Answer [1]}$。 - 第 $k$ 次调用的参数 $x$ 表示对第 $(k - 1)$ 张卡片的操作: - 若 $x = -1$,则丢弃该卡片; - 若 $0 \leq x$,则将卡片放置在桌面上当前最左数第 $x$ 张卡片的右侧;当 $x = 0$ 时,卡片置于桌面序列的最左侧。 - 参数需满足 $-1 \leq x \leq l$($l$ 为当前桌面卡片数),否则程序将被判定为 $\texttt{Wrong Answer [2]}$。 - 若调用 `DrawCard` 函数的次数不为 $(N + 1)$,程序将被判定为 $\texttt{Wrong Answer [3]}$。 --- 对于 Bruno 的策略,你应该实现以下的函数: ```cpp int Bruno(int N, int L, std::vector C) ``` 该函数在每次调用 `Anna` 函数后被调用恰好一次,总计 $Q$ 次。 第 $i$ 次调用($1 \leq i \leq Q$)对应第 $i$ 次占卜流程,需返回 $N$ 张卡牌中上面写着数字 $1$ 的卡牌数量。 - 参数 $N$ 表示 Anna 抽取的卡片总数。 - 参数 $L$ 表示桌面上的卡片数量。 - 参数 $C$ 为长度为 $L$ 的数组,其中 $C[l-1]$ 表示桌面上第 $l$ 张最左侧卡片($1 \leq l \leq L$)的数字。 - 若返回值不等于 $N$ 张卡牌中上面写着数字 $1$ 的卡牌数量,程序将被判定为 $\texttt{Wrong Answer [4]}$。 ### 注意事项 - 交互库是**非自适应的**。 - 程序可定义其他内部函数或全局变量,但需在匿名命名空间中声明以避免冲突。 - 由于洛谷评测系统的限制,Anna 和 Bruno 将在同一进程中运行。请注意清空。 - 禁止使用标准输入输出或通过其他方式与外部文件通信,但可将调试信息输出至标准错误流。 ### 编译与测试 下载附件中的压缩包,将以下文件置于同一目录: - $\boldsymbol{grader.cpp}$; - $\boldsymbol{Anna.cpp}$; - $\boldsymbol{Bruno.cpp}$; - $\boldsymbol{Anna.h}$; - $\boldsymbol{Bruno.h}$。 运行以下命令编译: ```bash g++ -std=gnu++20 -O2 -o grader grader.cpp Anna.cpp Bruno.cpp ``` 或直接运行压缩包中的 $\boldsymbol{compile.sh}$: ```bash ./compile.sh ```

输入格式

Sample Grader 输入格式如下: > $Q$ $N$ > $A_{1,1}$ $A_{1,2}$ $\cdots$ $A_{1,N}$\ > $A_{2,1}$ $A_{2,2}$ $\cdots$ $A_{2,N}$\ > $\vdots$\ > $A_{Q,1}$ $A_{Q,2}$ $\cdots$ $A_{Q,N}$

输出格式

Sample Grader 会向标准输出和标准错误流输出以下信息: - 若程序被判定为正确,Sample Grader 将以 $\texttt{Accepted: 100}$ 格式输出桌面上卡片数量的最大值。 - 若程序被判定为错误,Sample Grader 将以 $\texttt{Wrong Answer [1]}$ 格式输出错误类型。 若程序同时满足多个错误类型的条件,Sample Grader 仅报告其中一个。当检测到错误条件时,Sample Grader 可能终止执行。

说明/提示

### 样例交互 样例输入包含 $Q (= 2)$ 次占卜流程,Anna 从牌堆抽取的卡片数为 $N (= 5)$。 | 调用 | 返回值 | 调用 | 返回值 | |:-:|:-:|:-:|:-:| | $\texttt{Anna(5) }$ | $ $ | $\texttt{DrawCard(-1)}$ | $0 $ | | $\texttt{ }$ | $ $ | $\texttt{DrawCard(0) }$ | $1 $ | | $\texttt{ }$ | $ $ | $\texttt{DrawCard(-1)}$ | $0 $ | | $\texttt{ }$ | $ $ | $\texttt{DrawCard(1) }$ | $0 $ | | $\texttt{ }$ | $ $ | $\texttt{DrawCard(-1)}$ | $1 $ | | $\texttt{ }$ | $ $ | $\texttt{DrawCard(1) }$ | $-1$ | | $\texttt{Bruno(5, 3, [0, 1, 0]) }$ | $2$ | $\texttt{ }$ | $ $ | | $\texttt{Anna(5) }$ | $ $ | $\texttt{DrawCard(-1)}$ | $1 $ | | $\texttt{ }$ | $ $ | $\texttt{DrawCard(0) }$ | $1 $ | | $\texttt{ }$ | $ $ | $\texttt{DrawCard(1) }$ | $0 $ | | $\texttt{ }$ | $ $ | $\texttt{DrawCard(2) }$ | $1 $ | | $\texttt{ }$ | $ $ | $\texttt{DrawCard(-1)}$ | $0 $ | | $\texttt{ }$ | $ $ | $\texttt{DrawCard(1) }$ | $-1$ | | $\texttt{Bruno(5, 4, [1, 0, 1, 0])}$ | $3$ | $\texttt{ }$ | $ $ | 第一次占卜流程的操作步骤如下: 1. Anna 抽取第 $1$ 张卡,数字为 $0$。 2. Anna 选择将卡片置于桌面最左侧,桌面序列变为 $0$。接着抽取第 $2$ 张卡,数字为 $1$。 3. Anna 选择丢弃此卡。随后抽取第 $3$ 张卡,数字为 $0$。 4. Anna 选择将此卡放置在桌面上第 $1$ 张最左侧卡片的右侧,桌面序列变为 $0, 0$。接着抽取第 $4$ 张卡,数字为 $0$。 5. Anna 选择丢弃此卡。随后抽取第 $5$ 张卡,数字为 $1$。 6. Anna 选择将此卡放置在桌面上第 $1$ 张最左侧卡片的右侧,桌面序列变为 $0, 1, 0$。 此时,Bruno 看到的桌面序列为 $0, 1, 0$,推断 Anna 抽取的卡片中数字为 $1$ 的数量为 $2$(正确)。桌面上卡片数为 $L = 3$。 **第二次占卜流程**中,桌面上卡片数为 $L = 4$。 注:此样例输入不满足题目约束。附件压缩包中,`sample-01-in.txt` 对应样例输入 1,`sample-02-in.txt` 为满足约束的样例输入。 ### 数据范围 - $1\le Q\le 100$; - $N=900$; - $\forall 1\le i\le Q, 1\le j\le N$,$A_{i,j}\in \{0,1\}$。 ### 计分方式 若程序在任何测试用例中被判定为 $\texttt{Wrong Answer [1] – [4]}$(见【实现细节】)、TLE、MLE 或 RE 等,则得 $0$ 分。 若程序在所有测试用例中均被判定为正确,则得分由所有测试用例中所有占卜流程内调用 `DrawCard` 函数时参数满足 $0 \leq x$ 的最大次数决定。 设该次数为 $L$,得分规则如下: | 条件 | 得分 | |:-:|:-:| | $500 < L$ | $3$ | | $14 < L \leq 500$ | $\displaystyle \left\lfloor100 \times \left( \frac{2.5}{L - 11.5} \right)^{0.35}\right\rfloor$ | 向下取整($\lfloor \cdot \rfloor$) | | $L \leq 14$ | $100$ |