UOJ Logo Universal Online Judge

UOJ

#359. 【JOISC2017】Broken Device

附件下载 统计

Anna 和 Bruno 是两名考古学家,他们正在伊朗调查一处古代遗迹。

他们的分工如下:Anna 负责前往遗迹现场并发现文物,Bruno 则留在基地营地,对 Anna 传回的结果进行分析。

他们的调查计划持续 $Q = 1000$ 天。每天,Anna 都会通过一台通信设备,将当天的调查结果发送给 Bruno。每天的调查结果用一个整数 $X$ 表示。

Anna 每天只能使用通信设备一次。每次通信可以发送一个长度为 $N = 150$ 的 01 序列。

但是,这台通信设备已经损坏。在这个长度为 $N$ 的序列中,有若干个损坏的位置。对于一个损坏的位置,无论 Anna 实际设置的是 0 还是 1,Bruno 接收到的一定是 0。在 Anna 发送时,她可以知道哪些位置是损坏的。但是,Bruno 并不知道损坏位置在哪里。损坏位置的数量和具体位置每天都会变化。

由于通信不可靠,调查任务存在延期的风险。Anna 和 Bruno 请求正在伊朗参加国际编程比赛的你,编写一个程序来传达挖掘结果。

任务描述

你需要编写两个程序,协助 Anna 和 Bruno 完成通信:

  • 给定序列长度 $N$、需要发送的整数 $X$、损坏位置数量 $K$ 和损坏的所有位置 $P$,第一个程序应设置 Anna 所需发送的序列;
  • 给定 Bruno 接收到的序列 $A$,第二个程序需要还原出整数 $X$。

在通信设备正常工作的位置上,序列 $S$ 与序列 $A$ 的对应位置取值相同。在已被损坏的位置上,无论序列 S 在该位置上的取值为 0 还是 1,序列 $A$ 在该位置接收到的值恒为 $0$。

实现细节

你需要提交两个源文件。仅支持 C++ 语言。

Anna

第一个文件是 Anna.cpp。该文件用于设置 Anna 发送的序列,并需要实现以下函数。程序中应包含头文件 Annalib.h

void Anna( int N, long long X, int K, int P[] )
  • 对于每一个测试用例,该函数会被调用 $Q=1000$ 次。
    • 参数 N 表示将要发送的序列长度;
    • 参数 X 表示需要发送的整数;
    • 参数 K 表示损坏位置的数量;
    • 参数 P[] 是一个长度为 K 的数组,用于描述损坏位置。

在函数 Anna 中,必须调用以下函数:

void Set(int pos, int bit)
  • 该函数用于设置将要发送的序列 $S$ 中的某一位。
    • 参数 pos 表示需要设置的位置,pos 必须是一个介于 $0$ 到 $N−1$(含端点)之间的整数。注意,位置编号从 0 开始计数。如果该函数被调用时 pos 超出了该范围,你的程序将被判定为 Wrong Answer。不允许使用相同的参数 pos 调用该函数多于一次。如果同一个 pos 被设置多次,你的程序将被判定为 Wrong Answer
    • 参数 bit 表示在第 pos 个位置设置的值,bit 必须为 $0$ 或 $1$。如果使用了其他取值,你的程序将被判定为 Wrong Answer

在函数 Anna 中,函数 Set 必须被调用恰好 N 次。当函数 Anna 结束时,如果 Set 的调用次数不等于 N,你的程序将被判定为 Wrong Answer

如果 Anna 中的函数调用被判定为非法,你的程序将被立即终止。

Bruno

第二个文件是 Bruno.cpp。该文件用于还原表示调查结果的整数,并需要实现以下函数。程序中应包含头文件 Brunolib.h

long long Bruno(int N, int A[])
  • 对于每一个测试用例,该函数会被调用 $Q=1000$ 次。
    • 参数 N 表示 Bruno 接收到的序列长度;
    • 参数 A 是一个长度为 N 的整数数组,表示 Bruno 接收到的序列;
    • 函数 Bruno 必须还原出整数 X,并将其作为返回值返回。

评分方式

评测按照以下方式进行。如果你的程序被判定为 Wrong Answer,评测将立即终止。

  1. cnt = 0
  2. 调用一次函数 Anna
  3. S 为 Anna 函数设置的序列。将 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。程序必须在执行过程中不发生运行时错误。
  • 你的程序可以实现其他内部使用的函数,或使用全局变量。提交的程序会与测评器 grader 一起编译,形成一个可执行文件。所有全局变量和内部函数都应声明为 static,以避免与其他文件发生冲突。在实际评测中,AnnaBruno 将作为 两个独立的进程 被执行,因此 它们不能共享全局变量。
  • 在整个过程中,函数 AnnaBruno 都会被调用 $Q=1000$ 次。程序中使用的变量应当被正确初始化。
  • 你的程序不得使用标准输入或标准输出,也不得通过任何方式与其他文件进行通信。

编译与测试

你可以下载附加文件,其中包含一个用于测试你程序的示例评测器。 该压缩包中也包含一个你需要编写的程序的源代码示例。

示例评测器由一个源文件组成,文件名为 grader.cpp。 例如,如果你的程序是 Anna.cppBruno.cpp,你可以使用以下命令来编译程序。

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, \cdots, P_{K−1}$。这表示对于每个 $i$($0 \le i \le K − 1$),序列中的第 $P_i$ 个位置是损坏的。

示例评测器的输出格式

当程序正常结束时,示例评测器会向标准输出写出如下信息(实际输出中不包含引号):

  • 如果你的程序被判定为 Wrong Answer,示例评测器会以类似于 Wrong Answer 的格式输出错误类型,并立即终止程序。
  • 如果对 Anna 的每一次函数调用都未被判定为 Wrong Answer,示例评测器会输出 Accepted
    以及数值 $L^\ast$。关于 $L^\ast$ 的含义,请参见 Scoring(评分) 部分。

如果你的程序同时满足多种 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^\ast$ 为下述数值在所有测试用例中的最小值:
    • 最大的整数 $L \le 40$ 使得对于所有满足 $K \le L$ 的查询,Bruno 都能够正确地还原出整数 $X$。
  • 本题的得分按照如下方式计算:
    • 若 $L^\ast = 0$,得分为 $0$ 分;
    • 若 $1 \le L^\ast \le 14$,得分为 $8$ 分;
    • 若 $15 ≤ L^\ast ≤ 37$,得分为 $(L^\ast − 15) \times 2 + 41$ 分;
    • 若 $38 ≤ L^\ast ≤ 40$,得分为 $(L^\ast − 38) \times 5 + 90$ 分。

通信样例

下面给出了一个输入样例和对应的函数调用。注意,由于 $Q = 2, N = 3$,以下例子并不满足本题约束条件。

input

2
3 14 1
2
3 9 2
0 1

sample calls

Call Return Call Return
Anna(...)      
    Set(0, 0)  
      (none)
    Set(1, 0)  
      (none)
    Set(2, 1)  
      (none)
  (none)    
Bruno(...)      
  14    
Anna(...)      
    Set(0, 0)  
      (none)
    Set(1, 1)  
      (none)
    Set(2, 1)  
      (none)
Bruno(...)      
  9    

下面是 Anna(...), Bruno(...), Anna(...), Bruno(...) 调用中所涉及的参数:

参数 Anna(...) Bruno(...) Anna(...) Bruno(...)
N 3 3 3 3
X 14 9
K 1 2
P {2} {0, 1}
A {0, 0, 0} {0, 0, 1}