题目背景
请使用 C++ 17 / C++ 20 提交。
不要 #include "circuit.h"
。
请在文件头粘贴如下的语句:
#include <string>
#include <vector>
std::string solve(int N, int R, std::vector<int> U, std::vector<int> V);
int query(std::string s);
题目描述
这是一道交互题。本题中,交互库是非自适应的。
JOI 君正在玩一个电子积木。
该电子积木由 N 个 AND 组件、N 个 OR 组件和一个电路板组成。电路板包含 2N+1 个开关和 N 个组件插槽,每个组件插槽可以放置一个 AND 组件或 OR 组件。根据放置的组件和开关状态,电路板会输出 0 或 1。
电路说明
- 每个开关被分配一个从 0 到 2N 的编号,且每个开关有 ON(开启)或 OFF(关闭)两种状态。每个开关会按以下规则输出 0 或 1。
- 每个组件插槽被分配一个从 0 到 N−1 的编号。每个组件插槽也会按以下规则输出 0 或 1。
- 每个开关和组件插槽的输出值按从高编号到低编号的顺序确定。若开关和组件插槽编号相同,则先确定组件插槽的输出值。
-
对于 j=2N,2N−1,…,N 的开关:
- 若开关 j 为 OFF,则输出 0。
- 若开关 j 为 ON,则输出 1。
-
对于 j=N−1,N−2,…,0 的开关:
- 设组件插槽 j 的输出值为 x。
- 若开关 j 为 OFF,则输出 x。
- 若开关 j 为 ON,则输出 1−x。
-
对于组件插槽 i=N−1,N−2,…,0:
- 它连接到两个开关 Ui 和 Vi(满足 i<Ui<Vi≤2N)。
- 设开关 Ui 的输出为 x,开关 Vi 的输出为 y。
- 若组件插槽 i 放置的是 AND 组件,则输出 min(x,y)。
- 若组件插槽 i 放置的是 OR 组件,则输出 max(x,y)。
- 对于每个 j=1,2,…,2N,存在且仅存在一个 i(0≤i≤N−1)满足 Ui=j 或 Vi=j。
- 电路板的最终输出值等于开关 0 的输出值。
当 N=3,且 U0=1,V0=2,U1=3,V1=4,U2=5,V2=6 时,若在组件插槽 0 和 1 放置 AND 组件,在组件插槽 2 放置 OR 组件,其电路结构如下图所示。

JOI 君原本试图在所有组件插槽中放置 AND 组件,但实际混入了最多 R 个 OR 组件。由于两种组件外观相同,必须通过电路板的输出值来识别。你的任务是通过最多 1000 次查询,确定哪些组件插槽包含 OR 组件。每次查询的格式为:
- 指定所有 2N+1 个开关的状态。
- JOI 君将根据此配置返回电路板的输出值。
请根据电路板的连接结构和 OR 组件的数量上限,编写一个程序来解决此问题。
实现细节
你不需要,也不应该实现 main
函数。你应当实现以下的函数:
std::string solve(int N, int R, std::vector<int> U, std::vector<int> V)
- 此函数在每个测试点中仅被调用一次。
- 参数
N
表示组件插槽的数量 N。
- 参数
R
表示 OR 组件的数量上限 R。
- 参数
U
和 V
是长度为 N 的数组,其中 U[i]
和 V[i]
(0≤i≤N−1)表示组件插槽 i 连接的开关编号 Ui 和 Vi。
- 此函数必须返回一个长度为 N 的字符串
t
,且满足以下条件:
- 对每个 i=0,1,…,N−1,若组件插槽 i 包含 AND 组件,则
t[i]
必须为 &(&
);若包含 OR 组件,则 t[i]
必须为 |(|
)。
- 若返回的字符串
t
长度不为 N,程序将被判为 Wrong Answer [1]。
- 若
t
包含 & 或 | 以外的字符,程序将被判为 Wrong Answer [2]。
- 若实际组件类型与
t
描述不符,程序将被判为 Wrong Answer [3]。
你可以调用以下的函数:
int query(std::string s)
- 此函数用于向 JOI 君发起查询。
- 参数
s
必须是一个长度为 2N+1 且仅由 '0'
和 '1'
组成的字符串。对每个 j=0,1,…,2N:
- 若
s[j]
为 0,则开关 j 设为 OFF;
- 若
s[j]
为 1,则开关 j 设为 ON。
- 若
s
长度不为 2N+1,程序将被判为 Wrong Answer [4]。
- 若
s
包含 '0'
或 '1'
以外的字符,程序将被判为 Wrong Answer [5]。
- 此函数最多调用 1000 次。若超过此限制,程序将被判为 Wrong Answer [6]。
- 函数返回值是按
s
配置开关后电路板的输出值。
注意事项
- 你可以定义额外的辅助函数或全局变量以供内部使用。
- 你的程序不得使用标准输入/输出或其他文件交互,但可将调试信息输出到标准错误流。
- 实际评测程序是非自适应的(non-adaptive),即交互过程开始时答案已固定。
编译运行
你可以从【附件】中下载包含 Sample Grader 的压缩文件以测试程序。压缩文件中还包含一个示例源代码文件。
Sample Grader 为 grader.cpp
。测试时需将 grader.cpp
、circuit.cpp
和 circuit.h
置于同一目录。使用以下命令编译:
g++ -std=gnu++20 -O2 -o grader grader.cpp circuit.cpp
或执行压缩包中的 compile.sh
脚本。
./compile.sh
编译成功后,将生成可执行文件 grader
。
注意:实际评测程序与 Sample Grader 不同。 Sample Grader 以单进程运行,从标准输入读取数据并将结果写入标准输出。
输入格式
设 T 为函数 solve
应该返回的长度为 N 的字符串。样例评测程序从标准输入读取以下格式的数据:
N R
U0 V0
U1 V1
⋮
UN−1 VN−1
T
输出格式
样例评测程序将以下信息输出到标准输出:
- 若程序被判定为正确,输出查询调用次数如 Accepted: 22;
- 若程序被判定为任何类型的错误答案,输出错误类型如 Wrong Answer [4]。
样例评测程序在首次检测到错误条件时立即终止执行。若多个错误条件同时存在,仅显示其中一个。
1 1
1 2
|
|
3 3
1 2
3 4
5 6
&&|
&&|
提示
样例交互
样例交互 1
交互库调用 |
返回值 |
选手程序调用 |
返回值 |
solve(1, 1, [1], [2]) |
|
|
|
query("010") |
1 |
query("011") |
query("111") |
0 |
"|" |
|
首次调用 query
时的输出计算过程:
- 开关 1 设为 ON,开关 2 设为 OFF,因此开关 1 输出 1,开关 2 输出 0。
- 组件插槽 0 包含 OR 组件,连接的开关 1 和 2 分别输出 1 和 0,因此组件插槽 0 输出 max(1,0)=1。
- 开关 0 设为 OFF,而组件插槽 0 输出 1,因此开关 0 输出 1。
- 最终,电路板的输出为 1。
该样例满足所有子任务的限制。
样例交互 2
交互库调用 |
返回值 |
选手程序调用 |
返回值 |
solve(3, 3, [1, 3, 5], [2, 4, 6]) |
|
|
|
query("0001001") |
0 |
query("0001110") |
1 |
query("0000011") |
0 |
"&&|" |
|
题目描述中的电路图对应此示例。
该样例满足子任务 3,6∼9 的限制。
附件中:
- sample-01-in.txt 对应样例 1;
- sample-02-in.txt 对应样例 2;
- sample-03-in.txt 满足子任务 3,4,5,8,9 的限制;
- sample-04-in.txt 满足子任务 3,6∼9 的限制。
数据范围
- 1≤N≤8000;
- 1≤R≤min(N,120);
- 对每个 i(0≤i≤N−1),满足 i<Ui<Vi≤2N;
- 对于每个 j=1,2,…,2N,存在且仅存在一个 i(0≤i≤N−1)满足 Ui=j 或 Vi=j。
子任务
- Subtask 1 (1 pts):N=1;
- Subtask 2 (4 pts):N≤1000 且 R=1;
- Subtask 3 (5 pts):N≤1000;
- Subtask 4 (17 pts):Ui=i+1,Vi=N+1+i(0≤i≤N−1),且 R≤70;
- Subtask 5 (8 pts):Ui=i+1,Vi=N+1+i(0≤i≤N−1);
- Subtask 6 (23 pts):Ui=2i+1,Vi=2i+2(0≤i≤N−1),且 R≤70;
- Subtask 7 (8 pts):Ui=2i+1,Vi=2i+2(0≤i≤N−1);
- Subtask 8 (27 pts):R≤70;
- Subtask 9 (7 pts):无额外限制。