万能欧几里德算法
算法简介
有半群 \((G, \cdot)\)。给出 \(a, b, c, n, U, R\),满足 \(a, b, c, n \in \mathbb{N}\) 且 \(U, R \in G\) 且 \(\max\{a, c\} < b\),试求
通俗来讲,\(f(a, b, c, n, U, R)\) 表示有 \(n\) 个 \(R\)、其中第 \(x\) 个 \(R\) 前面共有 \(\lfloor \frac{ax + c}{b} \rfloor\) 个 \(U\) 时所有元素的乘积。
下文记 \(m = \lfloor \frac{an + c}{b} \rfloor\),表示 \(f(a, b, c, n, U, R)\) 中 \(U\) 的个数。
万能欧几里德算法能够通过 \(O(\log b)\) 次乘法运算计算出 \(f(a, b, c, n, U, R)\),它包含下述两种操作。
操作一:交换 \(a, b\)
考察第 \(y\) 个 \(U\),在它前面的 \(R\) 的个数即为 \(\lfloor \frac{ax + c}{b} \rfloor < y\) 中 \(x\) 的最大非负整数解:
此时有 \(-c - 1 < 0\),不满足递归条件,考虑把第一个 \(U\) 及之前的 \(R\) 单独拿出来,这样新的第 \(i\) 个 \(U\) 之前的 \(R\) 的个数为:
综上,我们有 \(f(a, b, c, n, U, R) = R^{\lfloor \frac{b - c - 1}{a} \rfloor} \cdot U \cdot f(b, a, (b - c - 1) \bmod a, m - 1, R, U) \cdot R^{n - \lfloor \frac{bm - c - 1}{a} \rfloor}\)。
操作二:将 \(a\) 变为 \(a \bmod b\)
考察第 \(x\) 个 \(R\),在它前面有 \(\lfloor \frac{ax + c}{b} \rfloor = \lfloor \frac{(a \bmod b)x + c}{b} \rfloor + \lfloor \frac{a}{b} \rfloor x\) 个 \(U\)。
因此我们有 \(f(a, b, c, n, U, R) = f(a \bmod b, b, c, n, U, U^{\lfloor \frac{a}{b} \rfloor} \cdot R)\)。
万能欧几里德算法
考虑交替进行操作一、二。
容易发现该算法的递归次数与计算 \(\gcd(a, b)\) 时使用的欧几里德算法完全相同,为 \(O(\log b)\) 次。
考虑使用快速幂计算算法中涉及的取幂运算。
计算 \(R^{\lfloor \frac{b - c - 1}{a} \rfloor}\) 与 \(R^{\lfloor \frac{b}{a} \rfloor}\) 显然需要 \(O(\log \frac{b}{a})\) 次乘法运算。
考虑分析计算 \(R^{n - \lfloor \frac{bm - c - 1}{a} \rfloor}\) 所需的乘法次数:
因此计算 \(R^{n - \lfloor \frac{bm - c - 1}{a} \rfloor}\) 只需要 \(O(1)\) 次乘法运算。
综上,每一层的乘法次数为 \(O(\log \frac{b}{a}) = O(\log b - \log a)\) 次。
递归到下一层时 \(a, b\) 交换,乘法次数为 \(O(\log a - \log(b \bmod a))\) 次。
发现上一层的 \(O(-\log a)\) 可以抵消掉下一层的 \(O(\log a)\),因此万能欧几里德算法总乘法次数为 \(O(\log b)\) 次。
代码实现
template <typename T>
T qpow(T x, ll y) {
T ret;
for (; y; y >>= 1, x = x * x)
if (y & 1) ret = ret * x;
return ret;
}
template <typename T>
T solve(ll a, ll b, ll c, ll n, T U, T R) {
ll m = (a * n + c) / b;
if (!m) return qpow(R, n);
return qpow(R, (b - c - 1) / a) * U *
solve(b % a, a, (b - c - 1) % a, m - 1, R, qpow(R, b / a) * U) *
qpow(R, n - (b * m - c - 1) / a);
}
例题
P5170【模板】类欧几里得算法
我们只需要设计合适的半群元素与乘法运算即可。
半群中的每一个元素代表一个由 \(U, R\) 组成的序列,维护五个信息:
-
\(U\) 的个数
-
\(R\) 的个数
-
每一个 \(R\) 「前面的 \(U\) 的个数」之和
-
每一个 \(R\) 「前面的 \(U\) 的个数」的平方和
-
每一个 \(R\) 「前面的 \(U\) 的个数」乘以「前面的 \(R\) 的个数加一」之和
容易发现维护上述五个信息即可支持合并序列,即乘法运算。
时间复杂度 \(O(T \log \max\{a, b, c\})\)。
ARC166E Fizz Buzz Difference
记 \(f(l, r) = \sum_{i = l}^r [a \mid i] - [b \mid i]\)。
先考虑求出 \(\max\{r - l \mid f(l, r) = n\}\)。
不难发现 \(\lim\limits_{r \to +\infty} f(l, r) = +\infty\) 且 \(|f(l, r) - f(l, r + 1)| \le 1\)。进而 \(\forall s \in N, \max\{r - l \mid f(l, r) = s\} < \max\{r - l \mid f(l, r) = s + 1\}\),因此转化为求解 \(\max\{r - l \mid f(l, r) \le n\}\)。
观察到最长的满足 \(f(l, r) \le n\) 的区间 \([l, r]\) 一定满足 \(a \mid l - 1 \land a \mid r + 1\)。这是因为如果 \(a \nmid l - 1\) 那么 \(f(l - 1, r) \le n\),如果 \(a \nmid r + 1\) 那么 \(f(l, r + 1) \le n\),都能导出矛盾。
因此又转化为求解 \(\max\{r - l \mid f(la + 1, ra - 1) \le n \}\)。我们会让 \(b\) 的倍数的出现位置尽可能多,也即让第一个 \(b\) 的倍数出现位置尽可能靠前。具体地,我们一定能使 \(b \mid la + \gcd(a, b)\)。于是直接列不等式就能解出区间长度的最大值。
求出了区间长度的最大值之后,我们还需要求出最小的 \(l\) 使得 \([la + 1, ra - 1]\) 中 \(b\) 的倍数个数取到理论最大值。这相当于找到 \(ax \bmod b \ge lim\) 的最小的非负整数 \(x\)。
不妨假设 \(\gcd(a, b) = 1\),如果不是可以让 \(a, b, lim\) 同时除以 \(\gcd(a, b)\) 而答案不变。先用扩展欧几里德算法解出 \(ax + by = 1\) 的一组解 \((x_0, y_0)\)。枚举 \(i = ax \bmod b\),所求即:
下式右项可以使用万能欧几里德算法求解。我们把 \(U\) 看作 \(-b\),把 \(R\) 看作 \(+x_0\),右项即求所有 \(R\) 处前缀和的最小值。容易设计出半群元素和乘法运算。
时间复杂度 \(O(T \log b)\)。
CF500G New Year Running
求出路径交后,从一端开始给上面的每个点从 \(0\) 开始依次编号。在此基础上画出两人的 \(s - t\) 图像:如果 \((x, y)\) 在某人的图像中则表示他时刻 \(x\) 时位于路径交上编号为 \(y\) 的节点。原问题转化为求出两人 \((x, y)\) 图像的横坐标最小的交点。
不难发现,每个人的 \(s - t\) 图像都由两部分组成:周期性重复的若干条斜率为 \(1\) 的线段,和周期性重复的若干条斜率为 \(-1\) 的线段。考虑把每个人 \(s - t\) 图像的两部分分开求交点。
如果求交点的两组周期性重复的线段斜率相同,那么有交等同于重合。容易使用扩展欧几里德算法 \(O(\log n)\) 求解。
否则,由于重复间隔(即对应人的路径长度的两倍)长度为偶数,排除掉不可能交在整点的情况后,剩下的情况只要横坐标范围有交就一定交在整点。记第一个人重复间隔为 \(a\),第二个人重复间隔为 \(b\)。第一个人的第 \(x\) 条线段和第二个人的第 \(y\) 条线段横坐标有交(\(x, y\) 从 \(0\) 开始编号),限制形如 \(l \le ax - by \le r\);如果最后的横坐标最小的交点是这两条线段的交点,那么答案形如 \(\frac{c + ax + by}{2}\)。因此,我们需要求出 \(\min\{ax + by \mid l \le ax - by \le r\}\)。
不妨假设 \(\gcd(a, b) = 1\),如果不是则一定可以转化。先用扩展欧几里德算法求出 \(ax - by = 1\) 的一组解 \((x_0, y_0)\),枚举 \(i = ax - by\),所求转化为:
\(l \le 0 \le r\) 的情况一定有 \((0, 0)\) 作为最优解,\(r < 0\) 的情况可以全部乘以 \(-1\) 转化为 \(l > 0\)。当 \(l > 0\) 时,记 \(\frac{p}{q} = \min\{\frac{x_0}{b}, \frac{y_0}{a}\}\),上式转化为:
类似上文的 ARC166E,最下式右项可以通过万能欧几里德算法求解。
时间复杂度 \(O(T \log n)\)。
CF868G El Toll Caves
不难猜到最优策略一定是第 \(i\) 天检查编号为 \(ik \bmod n, (ik + 1) \bmod n, (ik + 2) \bmod n, \dots, (ik + k - 1) \bmod n\) 的 \(k\) 个洞穴(洞穴编号从 \(0\) 开始)。这是因为宝藏在任何一个洞穴里的可能性都相等,我们希望每个洞穴被检查的次数尽可能平均。
记 \(f_i\) 表示宝藏在洞穴 \(i\) 时的期望天数。稍加推导不难发现:
容易发现这些转移连成了 \(\gcd(n, k)\) 条长为 \(\frac{n}{\gcd(n, k)}\) 环,每条环上的 \(f\) 完全相同,于是只需要考虑 \(\gcd(n, k) = 1\) 的情况即可。
此时,令 \(f_0\) 为主元,从 \(0\) 开始不断 \(+ k\),在环上走一圈即可 \(O(n)\) 解出 \(f_0\),进而求得 \(\frac{1}{n}\sum_{i = 0}^{n - 1} f_i\)。
考虑使用万能欧几里德算法加速「走一圈」的过程。每走一步,如果跨过了一个周期就先 \(\times \frac{1}{2}\) 再 \(+1\),否则直接 \(+1\)。容易发现走第 \(x\) 步之前共进行了 \(\lfloor \frac{kx}{n} \rfloor\) 次 \(\times \frac{1}{2}\),这对应着第 \(x\) 个 \(R\) 之前有 \(\lfloor \frac{kx}{n} \rfloor\) 个 \(U\)。
我们把 \(\times \frac{1}{2}\) 看作 \(U\),\(+1\) 看作 \(R\),对于每个半群元素维护:
-
\((k, b)\) 表示 \(x\) 经过该元素对应的 \(U, R\) 操作序列后变为了 \(kx + b\)
-
\((s_k, s_b)\) 表示 \(x\) 经过该元素对应的 \(U, R\) 操作序列在进行完每个 \(R\) 操作后的和为 \(s_k x + s_b\)
容易设计乘法运算,由于 \((k, b)\) 本质是矩阵,因此不难验证其满足结合律。
时间复杂度 \(O(T \log n)\)。

浙公网安备 33010602011771号