#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. Козак Вус і програмування

众所周知,科扎克·武斯有一台他童年时经常玩耍的机器人——阿特拉斯。今天,武斯意识到他从未尝试过为机器人编程执行其他操作,于是开始阅读说明书。他发现阿特拉斯的内存中存储着 4040 个编号从 11 开始的寄存器,每个寄存器包含 6464 位。这意味着每个寄存器由 64640011 组成。

武斯还了解到,可以通过以下 77 种命令对寄存器进行操作来编程机器人。为方便起见,我们将编号为 ii 的寄存器称为寄存器 ii,并用 aia_i 表示存储在第 ii 个寄存器中的数值:

  1. setValue(i, j)\texttt{setValue(i, j)} —— 将寄存器 ii 替换为寄存器 jj 的值。即用寄存器 jj 的每个位替换寄存器 ii 的对应位。换句话说,执行赋值操作 ai=aja_i = a_j
  2. setXor(i, j, k)\texttt{setXor(i, j, k)} —— 将寄存器 ii 替换为寄存器 jjkk 的逐位异或(XOR)结果。即用寄存器 jjkk 对应位的 XOR 结果替换寄存器 ii 的每个位。关于 XOR 操作的细节将在下文说明。
  3. setAnd(i, j, k)\texttt{setAnd(i, j, k)} —— 将寄存器 ii 替换为寄存器 jjkk 的逐位与(AND)结果。即用寄存器 jjkk 对应位的 AND 结果替换寄存器 ii 的每个位。关于 AND 操作的细节将在下文说明。
  4. setOr(i, j, k)\texttt{setOr(i, j, k)} —— 将寄存器 ii 替换为寄存器 jjkk 的逐位或(OR)结果。即用寄存器 jjkk 对应位的 OR 结果替换寄存器 ii 的每个位。关于 OR 操作的细节将在下文说明。
  5. shiftLeft(i, x)\texttt{shiftLeft(i, x)} —— 将寄存器 ii 的所有位向左移动 xx 位。关于移动操作的细节将在下文说明。
  6. shiftRight(i, x)\texttt{shiftRight(i, x)} —— 将寄存器 ii 的所有位向右移动 xx 位。关于移动操作的细节将在下文说明。
  7. setNot(i, j)\texttt{setNot(i, j)} —— 将寄存器 ii 替换为寄存器 jj 的逐位取反结果。即如果寄存器 jj 的对应位为 00,则将寄存器 ii 的对应位设为 11;如果为 11,则设为 00

两种位的 XOR 操作结果为 00(如果两位相同)或 11(如果两位不同)。

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

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

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

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

读完说明书后,科扎克·武斯立即想出了 66 个相当有趣的问题。稍作思考后,武斯意识到要为机器人编程解决某个具体问题,只需输入一组命令即可完成。假设 tt 表示你在某个问题中执行的命令数量。

以下是具体的子任务:

  • 子任务 1:(最高 66 分)寄存器 11 中存储数字 xx,其他所有寄存器全为 00。设 yy11(如果 xx 为偶数)或 00(如果 xx 为奇数)。任务是在机器人执行操作后,将数字 yy 存储到寄存器 22 中。你的得分为 6tmin(3,t)3\lfloor 6 - \sqrt[3]{t - \min(3, t)} \rfloor
  • 子任务 2:(最高 1010 分)寄存器 11 中存储 xx,寄存器 22 中存储 yy,其他所有寄存器全为 00。设 z=x+yz = x + y。任务是在机器人执行操作后,将数字 zz 存储到寄存器 33 中。注意,如果 zz 的二进制表示超过 6464 位,则寄存器 33 中只存储最低 6464 位。你的得分为 10tmin(260,t)3\lfloor 10 - \sqrt[3]{t - \min(260, t)} \rfloor
  • 子任务 3:(最高 1313 分)寄存器 11 中存储 xx。设 yyxx 二进制表示中 11 的数量。任务是在机器人执行操作后,将数字 yy 存储到寄存器 22 中。你的得分为 13log(tmin(1505,t)+1)\lfloor 13 - \log(t - \min(1505, t) + 1) \rfloor
  • 子任务 4:(最高 2323 分)寄存器 1122 中分别存储两个不同的数字 xxyy。设若 x>yx > y,则 a=0,b=1a=0, b=1;若 y>xy > x,则 b=0,a=1b=0, a=1。任务是在机器人执行操作后,将数字 aabb 分别存储到寄存器 3344 中。你的得分为 23tmin(92,t)2.5\lfloor 23 - \sqrt[2.5]{t - \min(92, t)} \rfloor
  • 子任务 5:(最高 1818 分)寄存器 11 中存储数字 xx。设 yyxx 二进制表示中 11 的数量。任务是在机器人执行操作后,将数字 2y12^{y}-1 存储到寄存器 11 中。你的得分为 18tmin(6560,t)4\lfloor 18 - \sqrt[4]{t - \min(6560, t)} \rfloor
  • 子任务 6:(最高 3030 分)设 aa 是一个包含 99 个非负且两两不同的整数的数组。对于 ii1199,寄存器 ii 中存储 aia_i。设 bb 是数组 aa 按升序排序后的结果。任务是在机器人执行操作后,对于 ii1199,寄存器 ii 中存储 bib_i。注意数组 aabb 的编号从 11 开始。你的得分为 30tmin(4644,t)3\lfloor 30 - \sqrt[3]{t - \min(4644, t)} \rfloor

如果未说明寄存器的初始值,则假定其初始值全为 00。所有数字范围在 0026412^{64}-1 之间。

科扎克·武斯不知怎的得知了解决每个问题所需的命令数量,但他还不清楚具体使用哪些命令,因此向你求助。他请求你找到一组命令序列,可以在任何可能的输入数据下解决这些问题。

请注意,你执行的命令数量不得超过 10510^{5}。如果超过,你将得到 00 分并获得「答案错误」判定。如果执行了无效的查询,你将得到 00 分并获得「运行时错误」判定。每个子任务的最终结果将存储在指定输出的寄存器中,其他寄存器中的值可以是任意值。

交互方式

对于每个子任务,你需要单独实现一个函数:

void solve()
  • 该函数不接受任何参数,也不返回任何值。

你可以使用以下函数:

void setValue(integer i, integer j)
  • 该函数将寄存器 ii (1i40)(1 \leq i \leq 40) 的值设为寄存器 jj (1j40)(1 \leq j \leq 40) 的值。
void setXor(integer i, integer j, integer k)
  • 该函数将寄存器 ii (1i40)(1 \leq i \leq 40) 的值设为寄存器 jj (1j40)(1 \leq j \leq 40)kk (1k40)(1 \leq k \leq 40) 的逐位 XOR 结果。
void setAnd(integer i, integer j, integer k)
  • 该函数将寄存器 ii (1i40)(1 \leq i \leq 40) 的值设为寄存器 jj (1j40)(1 \leq j \leq 40)kk (1k40)(1 \leq k \leq 40) 的逐位 AND 结果。
void setOr(integer i, integer j, integer k)
  • 该函数将寄存器 ii (1i40)(1 \leq i \leq 40) 的值设为寄存器 jj (1j40)(1 \leq j \leq 40)kk (1k40)(1 \leq k \leq 40) 的逐位 OR 结果。
void shiftLeft(integer i, integer x)
  • 该函数将寄存器 ii (1i40)(1 \leq i \leq 40) 的值向左移动 xx (0x64)(0 \leq x \leq 64) 位。
void shiftRight(integer i, integer x)
  • 该函数将寄存器 ii (1i40)(1 \leq i \leq 40) 的值向右移动 xx (0x64)(0 \leq x \leq 64) 位。
void setNot(integer i, integer j)
  • 该函数将寄存器 ii (1i40)(1 \leq i \leq 40) 的值设为寄存器 jj (1j40)(1 \leq j \leq 40) 的逐位取反结果。

样例

假设寄存器 11 中存储数字 66,寄存器 22 中存储数字 33,执行以下命令:

setValue(3, 1)
setXor(4, 1, 2)
setAnd(5, 1, 2)
setOr(6, 2, 1)
shiftLeft(2, 3)
shiftRight(1, 2)
setNot(7, 2)

则前七个寄存器的值将变为:[1,24,6,5,2,7,18446744073709551591][1, 24, 6, 5, 2, 7, 18446744073709551591]