类欧几里得算法
类欧几里得算法
一些可能会用到的取整等式:
- \(a \leq \left\lfloor\dfrac b c\right\rfloor \Leftrightarrow a \leq \dfrac b c\),\(a \geq \left\lceil\dfrac b c \right\rfloor \Leftrightarrow a \geq \dfrac b c\)
- \(a < \left\lfloor\dfrac b c \right\rfloor \Leftrightarrow ac < b\),\(a > \left\lceil\dfrac b c\right\rceil \Leftarrow a >\dfrac b c\)。
即,不等号方向与取整方向相同。
一、类欧几里得的公式推导
目标:
\(\sum\limits_{i = 0}^{n}\left\lfloor \dfrac{ai+b}{c} \right \rfloor\),\(\sum\limits_{i = 0}^{n} \left\lfloor\dfrac{ai+b}{c}\right\rfloor^2\),\(\sum\limits_{i = 0}^{n}i\left\lfloor\dfrac{ai+b}c\right\rfloor\)
设 \(f(a, b, c,n) = \sum\limits_{i = 0}^{n}\left\lfloor \dfrac{ai+b}{c} \right \rfloor\)
推导 f:
-
当 \(a, b\geq c\) 时:由于 \(a = \left\lfloor \dfrac a c\right\rfloor c+(a \bmod c)\), 可得:
\(f(a, b, c, n) = \left\lfloor \dfrac a c \right\rfloor \dfrac{n(n+1)}2{}+\left\lfloor\dfrac b c\right\rfloor (n+1)+\sum\limits_{i = 0}^{n}\left\lfloor\dfrac{(a \bmod c)i+(b \bmod c)} {c}\right\rfloor\)
\(= \left\lfloor \dfrac a c \right\rfloor \dfrac{n(n+1)}2{}+\left\lfloor\dfrac b c\right\rfloor (n+1)+f(a \bmod c, b \bmod c, c, n)\)
-
当 \(a, b < c\) 时:
\(f(a, b, c, n) =\sum\limits_{i = 0}^{n}\sum\limits_{j = 0}^{\left\lfloor\frac {ai+b} c\right\rfloor - 1}1 = \sum\limits_{j = 0}^{\left\lfloor \frac{an+b}c\right\rfloor - 1}\sum\limits_{i = 0}^{n}[j < \left\lfloor\frac {ai+b}c\right\rfloor]\)
将\(j < \left\lfloor\dfrac {ai+b}c\right\rfloor\) 条件改写成关于 \(i\) 的柿子:
\(j < \left\lfloor\dfrac {ai+b}c\right\rfloor \Leftrightarrow j +1 \leq \dfrac {ai+b}c \Leftrightarrow jc+c \leq ai+b \Leftrightarrow jc+c-b-1 < a_i \Leftrightarrow \left\lfloor\dfrac{jc+c - b - 1}a\right\rfloor < i\)
设 $m = \left\lfloor\dfrac {an+b}c\right\rfloor $, 原式化为:
\(f(a, b, c, n) = \sum\limits_{j = 0}^{m - 1}\sum\limits_{i = 0}^{n}[i > \left\lfloor\dfrac{jc+c -b - 1}a\right\rfloor ] = \sum\limits_{j = 0}^{m - 1}n - \left\lfloor\dfrac{jc + c - b - 1}a\right\rfloor\) \(= nm - f(c, c - b - 1, a, m - 1)\)。
综上:
\(f(a, b, c, n) = \begin{cases} \left\lfloor\dfrac b c\right\rfloor \times (n+1) \ \ \ \ \ \ a = 0 \\ \left\lfloor\dfrac a c\right\rfloor \dfrac {n(n+1)}2+\left\lfloor\dfrac b c\right\rfloor (n+1)+f(a\bmod c, b\bmod c, n) \ \ \ \ \ \ \ a, b \geq c \\ nm - f(c, c - b - 1, a, m - 1) \ \ \ \ \ \ \ \ \operatorname{otherwise} \ \ \ \ \operatorname{when} m = \left\lfloor\dfrac{an+b}c\right\rfloor \end{cases}\)
理解了最基础的类欧几里得算法,我们再考虑以下两个变种和式:
\(g(a, b, c, n) = \sum\limits_{i = 0}^{n}i\left\lfloor\dfrac{ai+b}c\right\rfloor , h(a, b, c, n) = \sum\limits_{i = 0}^{n}\left\lfloor\dfrac{ai+b}c\right\rfloor^2\)
推导 g:
当 \(a, b \geq c\) 时:有 \(g(a, b, c, n) = \left\lfloor\dfrac a c \right\rfloor \dfrac{n(n+1)(2n+1)}6 + \left\lfloor\dfrac b c\right\rfloor \dfrac{n(n+1)}2+g(a \bmod c, b \bmod c, c, n)\)。
当 \(a, b < c\) 时,设 $m = \left\lfloor\dfrac{an+b}c\right\rfloor, t = \left\lfloor\dfrac{cj +c - b - 1}a\right\rfloor $, , 则有:
\(g(a, b, c, n) = \sum\limits_{j = 0}^{m - 1}\sum\limits_{i = 0}^{n}[i > t]i = \sum\limits_{j = 0}^{m - 1}\dfrac{(n - t)(n+t+1)}2\)
\(= \dfrac 1 2[m(n+1)n - \sum\limits_{j = 0}^{m - 1}t^2 - \sum\limits_{j = 0}^{m - 1}t] = \dfrac 1 2[m(n+1)n - h(c, c - b - 1, a , m - 1) - f(c, c - b - 1, a, m - 1)]\)。
推导 h:
当 \(a, b \geq c\) 时:有
\(h(a, b, c, n) = \left\lfloor\dfrac{a}c\right\rfloor^2\dfrac{n(n+1)(2n+1)}6+\left\lfloor\dfrac b c\right\rfloor ^2(n+1)+h(a \bmod c, b \bmod c, c, n) \left\lfloor\dfrac a c\right\rfloor \left\lfloor\dfrac b c\right\rfloor n(n+1)+2\left\lfloor\dfrac a c\right\rfloor g(a \bmod c, b \bmod c,c, n)+2\left\lfloor\dfrac b c\right\rfloor f(a \bmod c, b \bmod c,c, n)\)
当 \(a, b < c\) 时,$m = \left\lfloor\dfrac{an+b}c\right\rfloor, t = \left\lfloor\dfrac{cj + c - b - 1}a\right\rfloor $
考虑把 \(n^2 = 2 \dfrac {n(n+1)}2 - n = 2(\sum\limits_{i = 0}^ni)-n\)
这样做的意义在于,添加变量 \(j\) 时只会出现一个求和算子,不会出现 \(\sum \times \sum\) 的形式。
\(h(a, b, c, n) = \sum\limits_{i = 0}^{n}\left\lfloor\dfrac{ai+b}c\right\rfloor^2 =\sum\limits_{i =0}^{n}[(2\sum\limits_{j = 1}^{\left\lfloor\frac{ai+b}c\right\rfloor }j) - \left\lfloor\dfrac{ai+b}c\right\rfloor]\)
\(=(2\sum\limits_{i = 0}^{n}\sum\limits_{j = 1}^{\left\lfloor\frac{ai+b}c\right\rfloor j}) - f(a, b, c, n)\) 。
化简前一部分:
\(\sum\limits_{i= 0}^{n}\sum\limits_{j = 0}^{\left\lfloor\frac{ai+b}c\right\rfloor - 1}(j+1) =\sum\limits_{j = 0}^{m - 1}(j+1)(n - t) = \dfrac {nm(m+1)}2 - \sum\limits_{j = 0}^{m - 1}(j+1)\left\lfloor\dfrac{jc+c - b - 1}a\right\rfloor\)
\(=\dfrac{nm(m+1)}2 - g(c, c - b - 1, a, m - 1) - f(c, c - b - 1, a, m - 1)\)。
因此 \(h(a, b, c, n) = nm(m+1) - 2g(c, c - b - 1, a, m - 1) - 2f(c, c -b - 1, a, m - 1) - f(a, b, c, n)\)
在实现时,由于三种函数之间互相递归,因此可以用一个结构体保存。
inline int S0(int n) {
return (n + 1) % mod;
}
inline int S1(int n) {
return (ll)(n + 1) * n % mod * inv2 % mod;
}
inline int S2(int n) {
return (ll)n * (n + 1) % mod * (2 * n + 1) % mod * inv6 % mod;
}
struct node {
int f, g, h;
node(int f = 0, int g = 0, int h = 0) : f(f), g(g), h(h) {}
} ;
inline node calc(int n, int a, int b, int c) {
if(!a) {
int v = b / c;
return node((ll)S0(n) * v % mod, (ll)S1(n) * v % mod, (ll)S0(n) * v % mod * v % mod);
}
if(a >= c || b >= c) {
int u = a / c, v = b / c;
node t = calc(n, a % c, b % c, c);
return node(add(add((ll)u * S1(n) % mod, (ll)v * S0(n) % mod), t.f), add(add((ll)u * S2(n) % mod, (ll)v * S1(n) % mod), t.g), add(t.h, add(add((ll)u * u % mod * S2(n) % mod, (ll)v * v % mod * S0(n) % mod), add(add((ll)u * v % mod * S1(n) % mod * 2 % mod, (ll)v * t.f % mod * 2 % mod), (ll)u * t.g % mod * 2 % mod))));
}
int m = ((ll)a * n + b) / c; node t = calc(m - 1, c, c - b - 1, a);
int v1 = dec((ll)n * m % mod, t.f), v2 = (ll)inv2 * dec((ll)m * n % mod * (n + 1) % mod, add(t.f, t.h)) % mod, v3 = dec((ll)n * m % mod * (m + 1) % mod, add(add((ll)2 * t.f % mod, (ll)2 * t.g % mod), v1));
return node(v1, v2, v3);
}
二、几何推导
将 \(\sum\limits_{i = 1}^{n}\left\lfloor\dfrac{ai+b}c\right\rfloor\) 看做函数 \(f(x) = \dfrac{ax+b}c\) 在 \([1, n]\) 处所有整点个数和,可以利用分割梯形和三角形得到表达式。
以 \(f\) 为例。
当 \(b \geq c\) 时,函数截距 \(\geq 1\),因此可以截出一个长为 \(n\),宽为 \(\left\lfloor\dfrac b c\right\rfloor\)的矩形,因此 \(f(a, b,c, n) = (n+1) \times \left\lfloor\dfrac b c\right\rfloor +f(a, b \bmod c, c, n)\)。
当 \(a \geq c\) 时,函数斜率 \(\geq 1\),设 \(c = \left\lfloor\dfrac a c\right\rfloor\),考虑直线 \(y = cx\),显然其永远在 \(y = \dfrac{ax+b}c\) 的下方,且随着 \(x\) 的增大,纵坐标差增大。显然 \(y = cx\) 的整点个数为 \(c \times \dfrac{n(n+1)}2\),将所有坐标映射为 \((x, y) \to (x, y - cx)\),即减去 \(y = cx\),容易发现不改变整点,因此 \(f(a, b, c, n) = c \times \dfrac {n(n+1)}2 + f(a\bmod c, b,c, n)\)。
当 \(a < c, b < c\) 时,考虑沿直线 \(y = x\) 翻折,得到 \(y = \dfrac{cx - b}{a}\),用长为 \(\left\lfloor\dfrac{an+b} c\right\rfloor\),宽为 \(n\) 的矩形减去下方三角形整点个数(不含三角形的斜边)。注意到函数与 \(x\) 轴截距 \(<1\),因此平移 \(y\) 轴变成 \(y = \dfrac{cx+c-b}a\),再平移直线变成 \(y = \dfrac{cx+c-b-1}a\) 后,即 \(f(a, b,c, n) = \left\lfloor\dfrac{an+b}c\right\rfloor \times n - f(c, c - b - 1, a, \left\lfloor \dfrac {an+b}c\right\rfloor-1)\)。
对于 \(g, h\) 同理,对于 \(g\),每个点的权值 \((x, y) = x\),\(h\) 为 \((x, y) = 2 \times y - 1\),容易发现它们再沿 \(y = x\) 翻转后可以互推。
三、万能欧几里得
万能欧几里得可以解决几乎所有类欧几里得可以解决的问题,其优势在于只用考虑两个信息的合并。
问题转化
类欧几里得通常有以下形式:
设 \(y = \left\lfloor\dfrac{ax+b}c\right\rfloor\),求:
\(\sum\limits_{x = 1}^{n}y, \ \ \sum\limits_{x = 1}^{n}xy, \ \ \sum\limits_{x = 1}^{n}y^2 \ \ \sum\limits_{x = 1}^{n}a^xy \ \ \sum\limits_{x = 1}^{n}a^xb^y \ \ \sum\limits_{x = 1}^{n}x^ay^b\)。
这些问题都可以规约到以下问题:
现在有一个初始为空的字符串,平面直角坐标系中有一条线段,初始在 $(1, 0) $ 位置,从左往右走,保证永远在线段的下方不超过线段,每次碰到 \(y = a\) 就在字符串末尾加入 \(U\),碰到 \(x = b\) 就在字符串末尾加入 \(R\)(等价于每次走到 \(x = a\) 最上方的整点,再走 \(R\) 将得到的 \(RU\) 序列进行保存), 碰到整点先加入 \(U\) 再加入 \(R\)。要求最后一个数是 \(R\),最后给定字符串函数 \(f(S)\),求 \(f(S)\)。
需要满足的是操作序列之间具有结合律。
例如求 \(\sum y\),设初始向量为 \(\begin{bmatrix} y \\ \sum y \\ 1 \end{bmatrix}\),设转移都是左乘矩阵,则 \(U = \begin{bmatrix} 1 \ \ 0 \ \ 1\\ 0 \ \ 1 \ \ 0 \\ 0 \ \ 0 \ \ 1 \end{bmatrix}\),\(R = \begin{bmatrix} 1 \ \ 0 \ \ 0 \\ 1 \ \ 1 \ \ 0 \\ 0 \ \ 0 \ \ 1\end{bmatrix}\)。
设 \(solve(a, b, c, n, R, U)\) 表示处理 \(y = \dfrac{ax+b}c\) 这条线段,\(x \in (0, n]\),\(R, U\) 表示每经过一个 \(x = a, y = b\) 添加的操作序列。
当 \(a \geq c\) 时,每次令 \(x+1\),都至少会加入 $\left\lfloor\dfrac a c\right\rfloor $ 个 \(U\),再加入一个 \(R\),因此 \(solve(a, b, c, n, R, U) = solve(a \bmod c, b, c, U^{\left\lfloor\frac a c\right\rfloor}R, U)\)。
当 \(a < c\) 时,考虑交换 \(a, c\) 和 \(R, U\),使得其进入第一部分,继续迭代。
第 \(p\) 个 \(R\) 在第 \(q\) 个 \(U\) 的前面当且仅当:\(\left\lfloor\dfrac{ap+b}c\right\rfloor <q\),即 \(\dfrac{ap+b}c< q \Rightarrow ap+b < qc \Rightarrow p \leq \dfrac{qc - b - 1}a \Rightarrow p \leq \left\lfloor\dfrac{qc - b - 1}a\right\rfloor\),因此第 \(q\) 个 \(U\) 之前有 \(\left\lfloor\dfrac{qc - b - 1}a\right\rfloor\) 个 \(R\),等于 \(\left\lfloor\dfrac{(q - 1)c+c - b - 1}a\right\rfloor\)
但我们要保证最后一个字符是 \(R\),即现在最后一个字符为 \(L\),考虑总的 \(R\) 个数减去最后一个 \(U\) 之前的 \(R\) 的个数 \(cnt\),预先加入 \(cnt\) 个 \(R\)。同时,由于 \(q\) 减去了 1,还需要考虑第一个 \(U\) 及之前的 \(R\)。设 \(m = \left\lfloor\dfrac{an+b}c\right\rfloor\),\(rem = n - \left\lfloor\dfrac{mc - b - 1}a\right\rfloor\) 可以得到:
\(solve(a, b, c, n, R, U) = R^{\left\lfloor\frac {c - b - 1}a\right\rfloor}U \times solve(c, (c - b - 1) \bmod a, a, m - 1, U, R) +R^{rem}\)。
递归边界为 \(m = 0\) 时返回 \(R^{n}\),\(n = 0\) 时返回 $\empty $。 设合并一次的时间复杂度为 \(O(C)\),总时间复杂度为 \(O(C \log \max(a, c))\)。
若题目没有保证 \(b < c\),则可以变为计算 \(U^{\left\lfloor\frac b c \right\rfloor}solve(a, b \bmod c, c, n, U, R)\)。
注意此时没有算 \(x = 0\) 的贡献,因为 \(cntu, cntr\) 的定义是含当前节点的。