Anna 和 Bruno 喜欢算命,并乐于一起玩各种风格的算命游戏。今天,他们将使用卡片进行算命,游戏规则描述如下。他们将进行 $Q$ 次游戏。
- 他们准备了许多写有 0 或 1 的卡片,将它们洗牌并堆叠在牌堆上。
- Anna 从牌堆中一次抽取一张卡片,共抽取 $N$ ($N = 900$) 张。Anna 和 Bruno 都知道 $N$ 的值。每当她抽出一张卡片时,她决定是将该卡片丢弃,还是将其放在桌子上。
- 如果她选择将卡片放在桌子上,她会将该卡片插入到桌上的卡片序列中。
- 更正式地说,当桌上有 $l$ 张卡片时,她指定一个非负整数 $x$ ($0 \le x \le l$),并将该卡片放在桌上从左往右数第 $x$ 张卡片的右侧。如果 $x = 0$,她将卡片放在桌上卡片序列的最左侧。
- 当 Anna 抽取并处理完 $N$ 张卡片后,她的过程结束。算命的结果是这 $N$ 张卡片中数字为 1 的卡片数量。
- 在 Anna 完成她的过程后,Bruno 查看桌上的卡片序列。利用这些信息,他需要猜出算命的结果。如果他猜对了,则算命成功。
当桌上的卡片越少时,算命被认为越精通。请编写一个程序来实现 Anna 和 Bruno 的策略,以在所有 $Q$ 次算命中取得成功。在本任务中,Anna 放在桌上的卡片越少,得分就越高。
实现细节
你需要提交两个文件。
第一个文件是 Anna.cpp。该文件旨在实现 Anna 的策略,并应实现以下函数。程序应使用预处理指令 #include 包含 Anna.h。
void Anna(int N)该函数被调用 $Q$ 次。第 $i$ 次调用 ($1 \le i \le Q$) 对应于第 $i$ 次算命中 Anna 的过程。- 参数 $N$ 是 Anna 抽取的卡片数量。
对于每次 Anna 函数的调用,该函数必须调用以下函数 $N + 1$ 次。
int DrawCard(int x)使用此函数,Anna 从牌堆中抽取一张卡片,并选择丢弃它或将其放在桌上。她通过第 $j$ 次调用 ($1 \le j \le N$) 该函数的返回值获得写在第 $j$ 张卡片上的数字。她通过第 $k$ 次调用 ($2 \le k \le N + 1$) 该函数的参数来指定对第 $(k - 1)$ 张卡片的操作。- 第 $j$ 次调用 ($1 \le j \le N$) 该函数的返回值是 0 或 1,代表写在第 $j$ 张卡片上的数字。
- 第 $(N + 1)$ 次调用该函数的返回值是 -1,代表 Anna 抽卡结束。
- 第 1 次调用该函数的参数 $x$ 必须满足 $x = -1$。如果不满足,你的程序将被判为 Wrong Answer [1]。
- 第 $k$ 次调用该函数的参数 $x$ 代表对第 $(k - 1)$ 张卡片的操作。如果 $x = -1$,则第 $(k - 1)$ 张卡片将被丢弃。如果 $0 \le x$,则第 $(k - 1)$ 张卡片将被放在桌上从左往右数第 $x$ 张卡片的右侧。如果 $x = 0$,则该卡片将被放在桌上卡片序列的最左侧。此处,参数必须满足 $-1 \le x \le l$,其中 $l$ 是当前桌上的卡片数量。如果不满足,你的程序将被判为 Wrong Answer [2]。
- 如果
DrawCard函数的调用次数不是 $N + 1$,你的程序将被判为 Wrong Answer [3]。
第二个文件是 Bruno.cpp。该文件旨在实现 Bruno 的策略,并应实现以下函数。程序应使用预处理指令 #include 包含 Bruno.h。
int Bruno(int N, int L, std::vector<int> C)该函数在每次Anna函数调用后被调用一次,总共调用 $Q$ 次。第 $i$ 次调用 ($1 \le i \le Q$) 对应于第 $i$ 次算命中 Bruno 的过程。它必须返回 Anna 抽取的卡片中数字为 1 的卡片数量。- 参数 $N$ 是 Anna 抽取的卡片数量。
- 参数 $L$ 是桌上的卡片数量。
- 参数 $C$ 是长度为 $L$ 的数组,其中
C[l-1]是桌上从左往右数第 $l$ 张卡片 ($1 \le l \le L$) 上写的数字。 - 如果
Bruno函数的返回值不等于 Anna 抽取的卡片中数字为 1 的卡片数量,你的程序将被判为 Wrong Answer [4]。
说明
- 你的程序可以实现其他函数供内部使用,或使用全局变量。提交的文件将与评测程序一起编译,并成为一个单一的可执行文件。所有全局变量和内部函数应声明在匿名命名空间中,以避免与其他文件冲突。在评测时,它将作为 Anna 和 Bruno 两个进程执行。Anna 的进程和 Bruno 的进程不能共享全局变量。
- 你的程序不得使用标准输入和标准输出。你的程序不得以任何方式与其他文件通信。但是,你的程序可以将调试信息输出到标准错误。
编译与运行
你可以从比赛网页下载包含示例评测程序的压缩包来测试你的程序。压缩包中还包含你程序的示例源文件。
示例评测程序是 grader.cpp。为了测试你的程序,将 grader.cpp、Anna.cpp、Bruno.cpp、Anna.h、Bruno.h 放在同一目录下,并运行以下命令来编译你的程序:
g++ -std=gnu++20 -O2 -o grader grader.cpp Anna.cpp Bruno.cpp
或者,你可以运行压缩包中包含的 compile.sh。
./compile.sh
编译成功后,将生成可执行文件 grader。
数据范围
所有输入数据满足以下条件: $1 \le Q \le 100$。 $N = 900$。 * $A_{i,j}$ 为 0 或 1 ($1 \le i \le Q, 1 \le j \le N$)。
评分
如果你的程序在任何测试用例中被判为任何类型的 Wrong Answer [1] – [4]、Time Limit Exceeded、Memory Limit Exceeded 或 Runtime Error,你的得分为 0 分。
如果你的程序在所有测试用例中都被判为正确,你的得分由所有测试用例中所有算命过程中调用 DrawCard 函数且参数 $0 \le x$ 的最大次数决定。设 $L$ 为该次数。你的得分将为:
- $500 < L$: 3 分
- $14 < L \le 500$: $\lfloor 100 \times (\frac{2.5}{L - 11.5})^{0.35} \rfloor$ 分
- $L \le 14$: 100 分