Anna 和 Bruno 是考古学家,他们正在伊朗考察遗迹。 他们的任务如下:Anna 访问遗迹并发现文物,Bruno 在大本营分析结果。 他们的考察计划持续 $Q(= 1\,000)$ 天。每天,Anna 使用通信设备将结果发送给 Bruno。每天的结果表示为一个整数 $X$。 Anna 每天只能使用一次通信设备。它能发送一个长度为 $N(= 150)$ 的由 $0$ 或 $1$ 组成的序列。 然而,设备坏了。长度为 $N$ 的序列中有若干个损坏的位置。对于损坏的位置,无论实际设置的值是多少,它总是发送值 $0$。当 Anna 发送序列时,她可以看到损坏位置的坐标。但是,Bruno 不知道这些位置。损坏位置的坐标和损坏位置的数量每天都会变化。 他们的考察有延误的风险。因为你是伊朗国际编程竞赛选手的候选人,Anna 和 Bruno 请你编写一个程序来发送他们的考察结果。
编写两个程序来实现 Anna 和 Bruno 之间的通信。 给定序列长度 $N$、要发送的整数 $X$、损坏位置的数量 $K$ 以及损坏位置的坐标 $P$,第一个程序设置 Anna 发送的序列 $S$。 给定 Bruno 接收到的序列 $A$,第二个程序恢复整数 $X$。
在通信设备正常工作的地方,序列 $S$ 和序列 $A$ 的值相同。在损坏的地方,无论序列 $S$ 的值如何,序列 $A$ 的值总是 $0$。
实现细节
你需要提交两个用同一种编程语言编写的文件。
第一个文件是 Anna.c 或 Anna.cpp。该文件设置 Anna 发送的序列,并实现以下函数。程序应包含 Annalib.h。
void Anna( int N, long long X, int K, int P[] )对于每个测试用例,该函数会被调用 $Q = 1\,000$ 次。- 参数 $N$ 是要发送的序列长度。
- 参数 $X$ 是要发送的整数。
- 参数 $K$ 是损坏位置的数量。
- 参数 $P[]$ 是一个长度为 $K$ 的序列,描述损坏位置的坐标。
在函数 Anna 中,必须调用以下函数。
void Set( int pos, int bit )此函数设置通信设备发送的序列 $S$ 中的一位。- 参数
pos是要设置的位置。pos必须是 $0$ 到 $N - 1$ 之间的整数(包含 $0$ 和 $N - 1$)。注意位置从 $0$ 开始计数。如果调用时参数超出此范围,你的程序将被判定为 Wrong Answer[1]。不允许对同一个pos参数调用此函数超过一次。如果对同一个参数调用超过一次,你的程序将被判定为 Wrong Answer[2]。 - 参数
bit是设置在序列第pos位的值。bit的值必须是 $0$ 或 $1$。如果调用时参数不是这两个值,你的程序将被判定为 Wrong Answer[3]。
- 参数
函数 Set 在函数 Anna 中必须恰好被调用 $N$ 次。当函数 Anna 结束时,如果函数 Set 被调用的次数不等于 $N$,你的程序将被判定为 Wrong Answer[4]。
如果 Anna 的函数调用被判定为无效,你的程序将被终止。
第二个文件是 Bruno.c 或 Bruno.cpp。该文件恢复表示考察结果的整数,并实现以下函数。程序应包含 Brunolib.h。
long long Bruno( int N, int A[] )对于每个测试用例,该函数会被调用 $Q = 1\,000$ 次。- 参数 $N$ 是 Bruno 接收到的序列长度。
- 参数 $A$ 是一个长度为 $N$ 的整数序列。它是 Bruno 接收到的序列。
- 函数
Bruno必须恢复 $X$ 的值并返回它。
评分方式
评分按以下方式进行。如果你的程序被判定为 Wrong Answer,它将立即终止。
(1) 令 cnt = 0。
(2) 调用一次函数 Anna。
(3) 令 $S$ 为函数 Anna 设置的序列。在序列 $S$ 中,将位置 $P$ 处的值设为 $0$,得到序列 $A$。以参数 $A$ 调用一次函数 Bruno。
(4) 令 cnt = cnt + 1。如果 cnt < Q,跳转到 (2)。如果 cnt = Q,跳转到 (5)。
(5) 你的程序将被评分。
重要提示
- 运行时间和内存使用量是根据评分方式的 (1)、(2)、(3)、(4) 计算的。
- 你的程序在 (2) 中的
Anna函数调用或 (3) 中的Bruno函数调用中不得被判定为 Wrong Answer。你的程序必须在没有运行时错误的情况下执行。 - 你的程序可以实现其他内部函数或使用全局变量。提交的程序将与评测程序一起编译,并成为一个单一的可执行文件。所有全局变量和内部函数都应声明为
static,以避免与其他文件冲突。由于 Anna 和 Bruno 的程序在评测时作为两个不同的进程执行,它们不能共享全局变量。 - 在此过程中,函数
Anna和Bruno各自被调用 $Q = 1\,000$ 次。你的程序使用的变量应适当地初始化。 - 你的程序不应使用标准输入和标准输出。你的程序不应以任何方式与其他文件通信。
编译与测试运行
你可以从竞赛网页下载包含示例评测程序的压缩包来测试你的程序。压缩包中还包含你的程序的示例源文件。
示例评测程序由一个源文件组成,即 grader.c 或 grader.cpp。例如,如果你的程序是 Anna.c 和 Bruno.c,或者 Anna.cpp 和 Bruno.cpp,你可以运行以下命令来编译你的程序。
- C
gcc -std=c11 -O2 -o grader grader.c Anna.c Bruno.c -lm - C++
g++ -std=c++14 -O2 -o grader grader.cpp Anna.cpp Bruno.cpp
编译成功后,将生成可执行文件 grader。
注意,实际的评测程序与示例评测程序不同。示例评测程序将作为一个单一进程执行,它将从标准输入读取输入数据并将结果写入标准输出。
示例评测程序的输入格式
示例评测程序从标准输入读取以下数据。 第一行包含一个整数 $Q$。 然后给出 $Q$ 个查询的信息。 每个查询的信息由以下两行组成。 第一行包含三个空格分隔的整数 $N, X, K$。这意味着要发送的序列长度为 $N$,Anna 要发送的整数为 $X$,且有 $K$ 个损坏位置。 * 第二行包含 $K$ 个空格分隔的整数 $P_0, P_1, \dots, P_{K-1}$。这意味着对于每个 $i (0 \le i \le K - 1)$,序列中第 $P_i$ 个位置是损坏的。
示例评测程序的输出格式
当程序成功终止时,示例评测程序会将以下信息写入标准输出。(引号实际上不会被写入。)
如果你的程序被判定为 Wrong Answer,示例评测程序会以“Wrong Answer [1]”的形式写入其类型,并且你的程序会被终止。
如果对 Anna 的每个函数调用都没有被判定为 Wrong Answer,示例评测程序会写入“Accepted”以及 $L^*$ 的值。关于 $L^*$ 的值,请参阅“子任务”。
如果你的程序被判定为多种类型的 Wrong Answer,示例评测程序只会报告其中一种。
数据范围
所有输入数据满足以下条件: $Q = 1000$ $N = 150$ $0 \le X \le 1\,000\,000\,000\,000\,000\,000$ $1 \le K \le 40$ $0 \le P_i \le N - 1 (0 \le i \le K - 1)$ $P_i < P_{i+1} (0 \le i \le K - 2)$
子任务
- 令 $L^*$ 为本任务所有测试用例中以下值的最小值:
- 满足以下条件的最大整数 $L \le 40$:对于每个 $K \le L$ 的查询,Bruno 都能回答出正确的 $X$ 值。
- 本任务的得分计算方式如下:
- 如果 $L^* = 0$,得分为 0 分。
- 如果 $1 \le L^* \le 14$,得分为 8 分。
- 如果 $15 \le L^* \le 37$,得分为 $(L^* - 15) \times 2 + 41$ 分。
- 如果 $38 \le L^* \le 40$,得分为 $(L^* - 38) \times 5 + 90$ 分。
样例
输入格式 1
2 3 14 1 2 3 9 2 0 1
输出格式 1
Accepted
说明
本样例展示了评测程序与 Anna 和 Bruno 函数的交互过程。注意,本样例不满足题目约束($Q=2, N=3$)。
对于第一个查询($N=3, X=14, K=1, P=\{2\}$):
Anna 被调用,设置序列 $S$。
Set(0, 0), Set(1, 0), Set(2, 1) 被调用。
Bruno 被调用,接收序列 $A=\{0, 0, 0\}$(因为位置 2 损坏)。
Bruno 返回 14。
对于第二个查询($N=3, X=9, K=2, P=\{0, 1\}$):
Anna 被调用,设置序列 $S$。
Set(0, 0), Set(1, 1), Set(2, 1) 被调用。
Bruno 被调用,接收序列 $A=\{0, 0, 1\}$(因为位置 0 和 1 损坏)。
Bruno 返回 9。