数字变换 (transform)
时间限制: 1.5 秒
空间限制: 512 MiB
相关文件: 题目目录
题目描述
小 C 设计了一种变换 ,若输入
中的整数,则输出也是
中的整数。
记 为按位异或运算,即 C++/Java/Python 中的
^ 运算符。
若 均为
内的整数,定义
。
若 为
内的整数,
为
内的整数。将
的二进制表示进行高位补零的操作,使其恰好为
位。
将会把这
个二进制位分为高三位、中三位、低三位三组并将其视为三个数字分别进行变换,具体如下图所示:

d8ba5ce4-c1cd-4a95-9d29-13deb7ce623d.png
记 为
变换的输入值,并定义
,
,则
为
变换的输出值。长为
的序列
是一个给定的参数序列,并且其中每个数字都是
之间的整数。
现在小 C 有 个经过
变换后得到的值,分别为
,小 C 想知道它们对应的输入分别是什么。
输入格式
从标准输入读入数据。
第一行两个正整数 。
第二行有 个非负整数,分别为
。
第三行有 个非负整数,分别为
。
输出格式
输出到标准输出。
输出一行 个非负整数,表示
对应的输入。
样例1输入
1 2
3 5
504
样例1输出
101
样例1解释
可以枚举可能的输入并验证。
若枚举到的输入为 。
对于 来说:
,
,
,
,
,故
。
对于 来说:
,
,
,
,
,故
。
因此若输入为 ,则输出为
,因此
是其对应的输入。
如果枚举的输入是别的数字,可以同上验证其输出不是 。
样例2
见题目目录下的 2.in 与 2.ans。
样例3
见题目目录下的 3.in 与 3.ans。
子任务
的测试数据满足:
,
。
的测试数据满足:
,
,
,
,且只有唯一的输入能够得到这些输出。
Solution
import java.io.BufferedInputStream;
import java.io.IOException;
public class Main {
private static int f(int x, int k) {
return (((x * x + k * k) & 7) ^ k);
}
private static int transform(int value, int k) {
int a = (value >>> 6) & 7;
int b = (value >>> 3) & 7;
int c = value & 7;
int nextA = b;
int nextB = c ^ f(b, k);
int nextC = a ^ f(c, k);
return (nextA << 6) | (nextB << 3) | nextC;
}
public static void main(String[] args) throws Exception {
FastScanner scanner = new FastScanner();
int n = scanner.nextInt();
int m = scanner.nextInt();
int[] keys = new int[m];
for (int i = 0; i < m; i++) {
keys[i] = scanner.nextInt();
}
int[] inverse = new int[512];
for (int start = 0; start < 512; start++) {
int value = start;
for (int key : keys) {
value = transform(value, key);
}
inverse[value] = start;
}
StringBuilder answer = new StringBuilder(n * 4);
for (int i = 0; i < n; i++) {
int output = scanner.nextInt();
if (i > 0) {
answer.append(' ');
}
answer.append(inverse[output]);
}
System.out.println(answer);
}
private static final class FastScanner {
private final BufferedInputStream input = new BufferedInputStream(System.in);
private final byte[] buffer = new byte[1 << 16];
private int pointer;
private int length;
private int read() throws IOException {
if (pointer >= length) {
length = input.read(buffer);
pointer = 0;
if (length <= 0) {
return -1;
}
}
return buffer[pointer++];
}
int nextInt() throws IOException {
int character;
do {
character = read();
} while (character <= ' ' && character != -1);
int value = 0;
while (character > ' ') {
value = value * 10 + character - '0';
character = read();
}
return value;
}
}
}