[R8D] Z形填数
数据规模:。
思路
Z 形填数就是经典的 Z 阶曲线(Morton code)。把行号 和列号 (从 开始)的二进制位交错排开,就得到这个格子填入的数字( 基下标),加 即为答案。具体地,第 位上 的位放进结果的第 位、 的位放进第 位。
这是因为:每次分形时,列在低位的 决定左/右(红黄、蓝绿在 轴的区分),行在低位的 决定上/下;先列后行的顺序对应偶数位放 、奇数位放 。
共 个格子,每个格子的位交错是 。
复杂度:时间 ,空间 (直接用 println 输出)。
仓颉实现
查看仓颉实现
import std.convert.*
import std.env.*
main() {
let reader = getStdIn()
let n = Int64.parse(reader.readln().getOrThrow())
var size: Int64 = 1
for (_ in 0..n) {
size *= 2
}
let S = size
for (r in 0..S) {
for (c in 0..S) {
var idx: Int64 = 0
var bit: Int64 = 0
while (bit < n) {
idx = idx | (((c >> bit) & 1) << (2 * bit))
idx = idx | (((r >> bit) & 1) << (2 * bit + 1))
bit += 1
}
print(idx + 1)
if (c < S - 1) {
print(" ")
}
}
println()
}
}
要点:
- Z 形分形递归展开后,填入数字正是行列二进制位交错的结果,无需真的递归模拟。