原题地址:郑州轻工业大学在线评测系统
题干
ZHY 与 LZC 两人因为工作原因经常不在同一个城市,但是他们很不喜欢别人有偷窥他们聊天内容的机会,于是他们决定自己编写一套通信软件。
现在 ZHY 将每次要传输的数据切分为一组 31 x N
(宽 x 高)的二进制数据(每行 31bit,共 N
行),因为数据量较大,所以需要做一些特殊的操作来校验数据在传输过程中是否发生比特变换(某一位上 0 变成 1 或 1 变成 0)。
现在,ZHY 在这组数据的左边添加一列,上面添加一行,这样就将数据拓展为了 32 x (N + 1)
,同时规定:
- 第一行最高位为无效位(其值不影响任何数据)
- 第一行中(除最高位外)的每一位用于标记当前列(不包括第一行)中
1
的奇偶数 - 从第二行开始的每一行的最高位用于标记当前行(不包括其本身)中
1
的奇偶数
当标识位为 1
时表示该标识对应的行/列上 1
的数量为偶数,否则为奇数。
按照上述规则,我们可将 1011111_00010011_01101011_10111001
(共 31bit
其中下划线为辅助标线,无实际意义)划分为下面这样的二维矩阵:
1 |
|
同理,我们可将0000000_00000000_00000000_00000000_0000000_00000000_00000000_00000000
(共 62bit
)划分为:
1 |
|
然而理想很美好,现实很残酷,ZHY 在编写解码软件时遇到了困难,希望你能够帮他写出核心代码。
输入格式
每行输入一个整数(范围:-2^31 ~ 2^31 - 1
),代表软件接收到的信息,直到读取到 EOF 为止(最少 2 行,最多 1024 行)。
TJJJ 不忍心看新生被 ZHY 折磨,于是提前处理了一下信息,所以我们可以保证数据中最多只有一个错误比特,且标识位一定没有发生比特翻转。
输出格式
请你纠正信息中的错误比特,然后将正确的信息以二进制形式输出(每行 31bit
).
样例输入 1
1 |
|
样例输出 1
1 |
|
样例输入 2
1 |
|
样例输出 2
1 |
|
提示
样例1
中的输入转为二进制后为:
1 |
|
样例2
中的输入转为二进制后为:
1 |
|
题目解释
计算标识位
这道题题干看起来似乎有点复杂,但是其实原理十分简单。现在,我们先把难度降低一些,假设每行算上校验位一共 8bit,一共 8 行。
为了方便后续说明坐标,行号从 A 开始计数。
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
---|---|---|---|---|---|---|---|---|
A | * | |||||||
B | 1 | 0 | 1 | 1 | 0 | 0 | 0 | |
C | 0 | 0 | 0 | 1 | 1 | 1 | 0 | |
D | 1 | 1 | 0 | 0 | 0 | 1 | 1 | |
E | 0 | 1 | 0 | 1 | 0 | 1 | 0 | |
F | 1 | 0 | 1 | 0 | 1 | 0 | 1 | |
G | 1 | 1 | 1 | 1 | 1 | 1 | 1 | |
H | 1 | 0 | 0 | 0 | 0 | 1 | 0 |
首先需要注意的是二进制的最右端是最低位,下标从 0 开始从最低位开始向最高位递增。
从题干中我们不难发现,A7
是一个无效位,其值不影响运算,所以我们直接将其忽略。下面我们先把 B 行提取出来演示一下如何计算标识位。
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
---|---|---|---|---|---|---|---|---|
B | 1 | 0 | 1 | 1 | 0 | 0 | 0 |
现在我们数一下这一行中一共有多少个 1,很明显,一共有 3 个,是奇数个,所以标识位应当为 0:
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
---|---|---|---|---|---|---|---|---|
B | 0 | 1 | 0 | 1 | 1 | 0 | 0 | 0 |
列的计算方法与行的一样,只不过是竖了过来,这样,我们可以算出其余所有行和列的标识位:
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
---|---|---|---|---|---|---|---|---|
A | * | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
B | 0 | 1 | 0 | 1 | 1 | 0 | 0 | 0 |
C | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 0 |
D | 1 | 1 | 1 | 0 | 0 | 0 | 1 | 1 |
E | 0 | 0 | 1 | 0 | 1 | 0 | 1 | 0 |
F | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 |
G | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
H | 1 | 1 | 0 | 0 | 0 | 0 | 1 | 0 |
读入数据
看到输入数据的格式可能又有很多同学蒙圈了——这该怎么读?
是需要把输入的十进制数转换为二进制吗?很显然不是。如果手动转换为二进制的话我们还需要处理负数补码的问题,我们直接使用位运算就可以处理数字中的二进制信息。
下面我们说几个常用的位处理方法:
1 |
|
解题思路
思路就非常简单了,我们先读入数据,然后计算出所有标识位,再将我们计算的标识位与输入数据中的标识位相对比,找出不一样的行和列就能确定错误位置,反转这个位置的值就是正确结果,如果没有不一样的标识位就说明输入的数据没有错误。
直接给出代码:
1 |
|