Java教程

优雅的万能欧几里得

本文主要是介绍优雅的万能欧几里得,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

优雅的万能欧几里得

取自 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\) 次)。

万能欧几里得问题要维护这样的一个过程:

  1. 一开始我们有一个空字符串 \(s\)。

  2. 考虑点从 \(O\) 移动到 \(P\) 的过程:

    1. 其 \(x\) 坐标每经过一个整点,就向 \(s\) 中加入字符 \(\text{X}\)。
    2. 其 \(y\) 坐标每经过一个整点,就向 \(s\) 中加入字符 \(\text{Y}\)。

注意在 \(O,P\) 处不加入字符。容易发现在 \(\gcd(A,B)=1\) 时,不会出现同时经过 \(x,y\) 上的整点。

下图是 \(P=(3,5)\) 时的例子,此时的字符串为 \(\text{YXYYXY}\)。

line.png

在实际的应用中,我们用 \(\text{X,Y}\) 指代任何可拼接且满足结合律的操作(如矩阵)。

问题求解

用四元组 \((A,B,\text{X},\text{Y})\) 描述这样的一个万能欧几里得问题,则可以如下递归求解:

  1. 若 \(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})\)。
  2. 若 \(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\)。

区间查询

考虑万能欧几里得的过程,容易发现其中只有两种操作:

  1. 快速幂
  2. 直接拼接

如果我们用一个节点描述一个操作,就可以用二叉树的结构维护拼接操作。

对于快速幂,只需要对于节点进行可持久化。

而万能欧几里得所产生的二叉树至多只有 $\log $ 层,在这样的二叉树上查询的复杂度与线段树相同。

这篇关于优雅的万能欧几里得的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!