优雅的万能欧几里得
取自 CTT 2022 Day4 T3 (或许是2021?)
问题描述
考虑用以下方法描述一个万能欧几里得问题:
有一条端点为 \((0,0)\rightarrow (A,B)\) 的有向线段 \(OP\),我们认为其两端都是空的。
其中 \(A,B\) 是自然数,且 \(\gcd(A,B)=1\)。(当 \(g=\gcd(A,B)\ne 1\) 时,可以先求 \(\frac{A}{g},\frac{B}{g}\) 的结果,然后将其复制 \(g\) 次)。
万能欧几里得问题要维护这样的一个过程:
-
一开始我们有一个空字符串 \(s\)。
-
考虑点从 \(O\) 移动到 \(P\) 的过程:
- 其 \(x\) 坐标每经过一个整点,就向 \(s\) 中加入字符 \(\text{X}\)。
- 其 \(y\) 坐标每经过一个整点,就向 \(s\) 中加入字符 \(\text{Y}\)。
注意在 \(O,P\) 处不加入字符。容易发现在 \(\gcd(A,B)=1\) 时,不会出现同时经过 \(x,y\) 上的整点。
下图是 \(P=(3,5)\) 时的例子,此时的字符串为 \(\text{YXYYXY}\)。
在实际的应用中,我们用 \(\text{X,Y}\) 指代任何可拼接且满足结合律的操作(如矩阵)。
问题求解
用四元组 \((A,B,\text{X},\text{Y})\) 描述这样的一个万能欧几里得问题,则可以如下递归求解:
- 若 \(B\ge A\),则每次在 \(x\) 增加之前, \(y\) 都会增加 \(\lfloor\frac{B}{A} \rfloor\) 个,可以转化为 \((A,B\mod A,\text{Y}\cdot \lfloor\frac{B}{A} \rfloor+\text{X},\text{Y})\)。
- 若 \(B<A\),则可以直接翻转坐标系,转化为求解 \((B,A,\text{Y},\text{X})\)。(而网上许多教程的翻转操作都需要处理复杂的边界条件)。
容易发现递归的问题同样是合法的万能欧几里得问题。
复杂度分析
设 \(l=\lfloor\frac{B}{A} \rfloor\),递归时需要处理 \(\text{Y}\cdot l\),这是一个快速幂操作,其复杂度为 \(\log l\)。
而 \(B\mod A=B-A\cdot l\leq \frac{1}{l+1} B\),所以所有快速幂的复杂度总和为 \(\log A+\log B\)。
区间查询
考虑万能欧几里得的过程,容易发现其中只有两种操作:
- 快速幂
- 直接拼接
如果我们用一个节点描述一个操作,就可以用二叉树的结构维护拼接操作。
对于快速幂,只需要对于节点进行可持久化。
而万能欧几里得所产生的二叉树至多只有 $\log $ 层,在这样的二叉树上查询的复杂度与线段树相同。