定义斐波那契数列 \(F_0 = F_1 = 1, F_i = F_{i-2}+F_{i-1}(i\geq 2)\)。 \(x \in \mathbb N\) 的齐肯多夫表示 \(\left<c_1,c_2, \cdots,c_k\right>\) 满足 \(c_1 > 0, c_i > c_{i - 1} + 1\) 且 \(\sum_{i=1}^k F_{c_i} = x\)。 齐肯多夫定理是说,对于任意的 \(x\),这样的表示存在且唯一。 存在性:我们取出最大的 \(F_i\) 满足 \(F_i \leq x\),并令 \(x' \gets x - F_i\)。此时 \(x'=x-F_i<F_{i + 1}-F_i = F_{i-1}\),从而接下来 \(x'\) 选取的数最多为 \(F_{i - 2}\)。 对于充分大的 \(F_n\),我们用一个长为 \(n - 1\) 的 \(01\) 串表示 \(F_1 \sim F_{n - 1}\) 是否被选取。显然长为 \(n - 1\) 的、没有相邻的 \(1\) 的 \(01\) 串的个数为 \(F_{n}\);同时可以归纳证明,无论我们如何选取,得到的和总是 \(< F_n\)。从而根据存在性,\([0, F_n)\) 内的每个数都有恰好一种表示。 构造一个给定自然数 \(x\) 的齐肯多夫表示是容易的,与存在性证明的归纳方法类似,\(x > 0\) 时选出最大的 \(F_i \leq x\) 并递归构造 \(x - F_i\) 即可。 计算 \(\left<x_1, x_2, \cdots, x_k\right> + \left<y_1, y_2, \cdots, y_k\right>\)。 先简单相加得到 \(z_i = x_i + y_i\),此时棘手的是 \(z_i \gt 1\) 的位置。 我们考虑从高位到低位逐步调整,即假设当前位为 \(i\),已经保证 \((i, k]\) 的位合法。 设 \(\text{Carry}(o)\) 表示从第 \(o\) 位开始不断向高位进位的过程,即如下代码: 我们 \(\text{Carry}(i)\) 之后,不难发现若仍有 \(z_i \gt 1\),那么 \(z_{i + 1} = 0\)。 此时我们拆解 \(2F_i = F_i + F_{i - 1} + F_{i - 2} = F_{i + 1} + F_{i - 2}\),即 \(z_i \gets z_i - 2, z_{i + 1} \gets 1, z_{i - 2} \gets z_{i - 2} + 1\)。 做完上述操作后,我们仍要 \(\text{Carry}(i+1), \text{Carry}(i)\) 来保证高位的合法性。 定义势能为 \(\sum z_i\),那么 \(\text{Carry}\) 每循环一次势能就会 \(-1\),其余操作不改变势能。因此时间复杂度为 \(\mathcal O(k)\)。 计算 \(\left<x_1, x_2, \cdots, x_k\right> - \left<y_1, y_2, \cdots, y_k\right>\)。保证 \(x\) 代表的数大于等于 \(y\) 代表的数。 先令 \(z_i = x_i - y_i\),美观起见用 \(\bar{1}\) 表示 \(-1\)。 我们仍然是从高位向低位调整,逐步把 \(z\) 重构成只包含 \(0, 1, 2\) 的序列,再应用加法的做法。 同时,由于 \(x \geq y\),我们任意时刻第一个非 \(0\) 位一定不是 \(\bar{1}\),因此我们只需要设计 \(1, 2\) 开头的转化即可。 时间复杂度依旧是 \(\mathcal O(k)\)。 给定 \(N = \sum_{i=1}^n a_i F_i\),求它的齐肯多夫表示。\(n \leq 10^6, a_i \leq 10^{18}\)。 令 \(N_1 = \sum_{i=1}^n \lfloor \frac{a_i}2\rfloor F_i\),\(N_2 = \sum_{i=1}^n (a_i \bmod 2)F_i\)。 那么可以递归计算 \(N_1\),再计算 \(N = N_1 + N_1 + N_2\)。 时间复杂度 \(\mathcal O(n \log a_i)\)。 计算 \(\left<x_1, x_2, \cdots, x_k\right> \times \left<y_1, y_2, \cdots, y_k\right>\)。齐肯多夫定理
证明
齐肯多夫表示的基本运算
加法
void Carry(int o) {
while (z[o] && z[o + 1]) --z[o], --z[o + 1], ++z[o += 2];
}
减法
正则化
乘法