随记 – 五月二日 – 初探格雷码
格雷码(Gray code)是一种任意两相邻项有且仅有一位不同的二进制编码。
直观来看,其构造方式如下:假如我们构造出了格雷码,现在考虑构造位格雷码。我们将前位复制一遍,然后反转在原序列中的位置,也即;然后在最后项格雷码的左侧分别添上。由此有。
实际操作时,可以采用相邻两项的异或值与前缀异或和快速构造。假若有与的异或值序列,那么便有,同时有。
例如,前8项格雷码的二进制表示为:,相邻两项异或值为。
下面给出一个构造位格雷码的简单实现。更高效的实现和证明参见OI Wiki。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
inl void Gray (int n, int g[]) { for (int w = 0; w < n; ++w) { g[1<<w] = 1<<(w<<1); for (int i = 1; i < 1<<w; ++i) g[i + (1<<w)] = g[i]; } for (int i = 1; i < 1<<n; ++i) g[i] ^= g[i - 1]; }
格雷码主要有以下两个重要性质:
- 构成一个的全排列。
- 相邻两项恰有位不同。
假若我们需要构造一个到的全排列,并且考虑相邻两项的异或的算术总和最小,那么最优解一定是格雷码。同时,项格雷码的遍历仅需要作次二进制位的变换;而由于异或具有结合律与相异性,可以利用其构造互不相同的状态的表示,因此容易出现在与异或、最小异或代价等的构造题目中。
题目:
- CSP-S 2019 T1 格雷码:递归构造格雷码。
- AtCoder ARC 138 D – Differ By K-bits / 题解:如果相邻两项的二进制表示恰有位不同呢?(对于的特例?
- CF1673F. Anti-Theft Road Planning:相异状态的异或和表示方法,但是二维,且代价最小。
- Hint: 考虑将一维格雷码的构造推广到二维矩阵上。