#HK5273. 「UOI 2019 Stage 4 Day1」科扎克·武斯与编程
「UOI 2019 Stage 4 Day1」科扎克·武斯与编程
注意事项
在 LibreOJ 上,由于语言限制,目前只支持以下语言的提交:
- C++(标准为 C++ 14 及以上)
请在提交源代码前添加 #include "grader.h"。
题目描述
题目译自 Ukrainian Olympiads in Informatics 2019 Stage 4 Day1 T2. Козак Вус і програмування
众所周知,科扎克·武斯有一台他童年时经常玩耍的机器人——阿特拉斯。今天,武斯意识到他从未尝试过为机器人编程执行其他操作,于是开始阅读说明书。他发现阿特拉斯的内存中存储着 个编号从 开始的寄存器,每个寄存器包含 位。这意味着每个寄存器由 个 和 组成。

武斯还了解到,可以通过以下 种命令对寄存器进行操作来编程机器人。为方便起见,我们将编号为 的寄存器称为寄存器 ,并用 表示存储在第 个寄存器中的数值:
- —— 将寄存器 替换为寄存器 的值。即用寄存器 的每个位替换寄存器 的对应位。换句话说,执行赋值操作 。
- —— 将寄存器 替换为寄存器 和 的逐位异或(XOR)结果。即用寄存器 和 对应位的 XOR 结果替换寄存器 的每个位。关于 XOR 操作的细节将在下文说明。
- —— 将寄存器 替换为寄存器 和 的逐位与(AND)结果。即用寄存器 和 对应位的 AND 结果替换寄存器 的每个位。关于 AND 操作的细节将在下文说明。
- —— 将寄存器 替换为寄存器 和 的逐位或(OR)结果。即用寄存器 和 对应位的 OR 结果替换寄存器 的每个位。关于 OR 操作的细节将在下文说明。
- —— 将寄存器 的所有位向左移动 位。关于移动操作的细节将在下文说明。
- —— 将寄存器 的所有位向右移动 位。关于移动操作的细节将在下文说明。
- —— 将寄存器 替换为寄存器 的逐位取反结果。即如果寄存器 的对应位为 ,则将寄存器 的对应位设为 ;如果为 ,则设为 。
两种位的 XOR 操作结果为 (如果两位相同)或 (如果两位不同)。

两种位的 AND 操作结果为 (如果两位均为 )或 (如果至少有一位为 )。

两种位的 OR 操作结果为 (如果两位均为 )或 (如果至少有一位为 )。

寄存器向左移动 位的操作结果为:每个位等于原始寄存器中右侧 位的位置上的位,如果右侧没有 位的位置,则该位为 。

寄存器向右移动 位的操作结果为:每个位等于原始寄存器中左侧 位的位置上的位,如果左侧没有 位的位置,则该位为 。

读完说明书后,科扎克·武斯立即想出了 个相当有趣的问题。稍作思考后,武斯意识到要为机器人编程解决某个具体问题,只需输入一组命令即可完成。假设 表示你在某个问题中执行的命令数量。
以下是具体的子任务:
- 子任务 1:(最高 分)寄存器 中存储数字 ,其他所有寄存器全为 。设 为 (如果 为偶数)或 (如果 为奇数)。任务是在机器人执行操作后,将数字 存储到寄存器 中。你的得分为 。
- 子任务 2:(最高 分)寄存器 中存储 ,寄存器 中存储 ,其他所有寄存器全为 。设 。任务是在机器人执行操作后,将数字 存储到寄存器 中。注意,如果 的二进制表示超过 位,则寄存器 中只存储最低 位。你的得分为 。
- 子任务 3:(最高 分)寄存器 中存储 。设 为 二进制表示中 的数量。任务是在机器人执行操作后,将数字 存储到寄存器 中。你的得分为 。
- 子任务 4:(最高 分)寄存器 和 中分别存储两个不同的数字 和 。设若 ,则 ;若 ,则 。任务是在机器人执行操作后,将数字 和 分别存储到寄存器 和 中。你的得分为 。
- 子任务 5:(最高 分)寄存器 中存储数字 。设 为 二进制表示中 的数量。任务是在机器人执行操作后,将数字 存储到寄存器 中。你的得分为 。
- 子任务 6:(最高 分)设 是一个包含 个非负且两两不同的整数的数组。对于 从 到 ,寄存器 中存储 。设 是数组 按升序排序后的结果。任务是在机器人执行操作后,对于 从 到 ,寄存器 中存储 。注意数组 和 的编号从 开始。你的得分为 。
如果未说明寄存器的初始值,则假定其初始值全为 。所有数字范围在 到 之间。
科扎克·武斯不知怎的得知了解决每个问题所需的命令数量,但他还不清楚具体使用哪些命令,因此向你求助。他请求你找到一组命令序列,可以在任何可能的输入数据下解决这些问题。
请注意,你执行的命令数量不得超过 。如果超过,你将得到 分并获得「答案错误」判定。如果执行了无效的查询,你将得到 分并获得「运行时错误」判定。每个子任务的最终结果将存储在指定输出的寄存器中,其他寄存器中的值可以是任意值。
交互方式
对于每个子任务,你需要单独实现一个函数:
void solve()
- 该函数不接受任何参数,也不返回任何值。
你可以使用以下函数:
void setValue(integer i, integer j)
- 该函数将寄存器 的值设为寄存器 的值。
void setXor(integer i, integer j, integer k)
- 该函数将寄存器 的值设为寄存器 和 的逐位 XOR 结果。
void setAnd(integer i, integer j, integer k)
- 该函数将寄存器 的值设为寄存器 和 的逐位 AND 结果。
void setOr(integer i, integer j, integer k)
- 该函数将寄存器 的值设为寄存器 和 的逐位 OR 结果。
void shiftLeft(integer i, integer x)
- 该函数将寄存器 的值向左移动 位。
void shiftRight(integer i, integer x)
- 该函数将寄存器 的值向右移动 位。
void setNot(integer i, integer j)
- 该函数将寄存器 的值设为寄存器 的逐位取反结果。
样例
假设寄存器 中存储数字 ,寄存器 中存储数字 ,执行以下命令:
setValue(3, 1)
setXor(4, 1, 2)
setAnd(5, 1, 2)
setOr(6, 2, 1)
shiftLeft(2, 3)
shiftRight(1, 2)
setNot(7, 2)
则前七个寄存器的值将变为:。