类欧几里得算法学习笔记
类欧几里得算法
类欧几里得算法可以在\(O(log_2\max\{a,b\})\)的时间内求解形如\(\sum_{i=0}^n\lfloor \frac{a\cdot i+b}{c} \rfloor\)的式子,而他的求解过程酷似欧几里得算法,故而得名。
基础款
令\(f\left( a,b,c,n \right) = \sum_{i=0}^n \left\lfloor \frac{a\cdot i+b}{c} \right\rfloor\)
-
case 1:\(a=0\)
\[f\left( a,b,c,n \right) = \left\lfloor \frac{b}{c} \right\rfloor\cdot \left( n+1 \right) \] -
case 2:\(a\ge c {\kern 5pt} || {\kern 5pt} b\ge c\)
\[\begin{aligned} f\left( a,b,c,n \right)&=\sum_{i=0}^n\left\lfloor \frac{a\cdot i+b}{c} \right\rfloor \\ &=\sum_{i=0}^n\left\lfloor \frac{(\left\lfloor \frac{a}{c} \right\rfloor \cdot c+a\%c)\cdot i+\left\lfloor \frac{b}{c} \right\rfloor\cdot c+b\%c}{c} \right\rfloor \\ &=\sum_{i=0}^n\left\lfloor \frac{a}{c} \right\rfloor\cdot i+\sum_{i=0}^n\left\lfloor \frac{b}{c} \right\rfloor+\sum_{i=0}^n\left\lfloor \frac{(a\%c)\cdot i+b\%c}{c} \right\rfloor \\ &=\left\lfloor \frac{a}{c} \right\rfloor\cdot \frac{n\cdot (n+1)}{2}+\left\lfloor \frac{b}{c} \right\rfloor\cdot (n+1)+f\left( a\%c,b\%c,c,n \right) \end{aligned} \] -
case 3:\(a < c {\kern 5pt} \&\& {\kern 5pt} b < c\)
先考虑一个问题:已知\(\left\lfloor \frac{a\cdot i+b}{c} \right\rfloor=k\),求\(i\)的范围,以上均为正整数。\[\begin{aligned} &{\kern 16pt} k\le \frac{a\cdot i+b}{c}<k+1 \\ &\Leftrightarrow k\cdot c-b\le a\cdot i<c\cdot (k+1)-b \\ &\Leftrightarrow\left\lfloor \frac{k\cdot c-b+a-1}{a} \right\rfloor\le i \le \left\lfloor \frac{c\cdot (k+1)-b+a-1}{a} \right\rfloor-1 \end{aligned} \]我们变换求和的方法,枚举\(k\)
\[\begin{aligned} f\left( a,b,c,n \right) &=\sum_{i=1}^n\left\lfloor \frac{a\cdot i+b}{c} \right\rfloor \\ &=\sum_{k=0}^{\left\lfloor \frac{a\cdot n+b}{c} \right\rfloor-1}\left( \left\lfloor \frac{c\cdot (k+1)-b+a-1}{a} \right\rfloor-1-\left\lfloor \frac{k\cdot c-b+a-1}{a} \right\rfloor+1\right)\cdot k+ \\ &{\kern 15pt}\left( n-\left\lfloor \frac{\left\lfloor \frac{a\cdot n+b}{c} \right\rfloor\cdot c-b+a-1}{a} \right\rfloor+1 \right)\cdot \left\lfloor \frac{a\cdot n+b}{c} \right\rfloor \\ &=\sum_{k=1}^{\left\lfloor \frac{a\cdot n+b}{c} \right\rfloor}\left\lfloor \frac{c\cdot k-b-1}{a} \right\rfloor \cdot k-\sum_{k=0}^{\left\lfloor \frac{a\cdot n+b}{c} \right\rfloor-1} \left\lfloor \frac{c\cdot k-b-1}{a} \right\rfloor \cdot k-\sum_{k=0}^{\left\lfloor \frac{a\cdot n+b}{c} \right\rfloor-1}\left\lfloor \frac{c\cdot (k+1)-b-1}{a} \right\rfloor+\\ &{\kern 15pt}\left( n-\left\lfloor \frac{\left\lfloor \frac{a\cdot n+b}{c} \right\rfloor\cdot c-b-1}{a} \right\rfloor \right)\cdot \left\lfloor \frac{a\cdot n+b}{c} \right\rfloor \\ &=\left\lfloor\frac{a\cdot n+b}{c}\right\rfloor\cdot n-\sum_{k=0}^{\left\lfloor\frac{a\cdot n+b}{c}\right\rfloor-1}\left\lfloor \frac{c\cdot (k+1)-b-1}{a} \right\rfloor \\ &=\left\lfloor\frac{a\cdot n+b}{c}\right\rfloor\cdot n-f\left( c,c-b-1,a, \left\lfloor\frac{a\cdot n+b}{c}\right\rfloor-1\right) \end{aligned} \]
我们发现上面的计算过程与欧几里得算法类似,复杂度是\(O(log_2\max\{a,b\})\)
进阶款
$g\left( a,b,c,n \right)=\sum_{i=0}^n\left\lfloor \frac{a\cdot i+b}{c} \right\rfloor^2 $
$h\left( a,b,c,n \right)=\sum_{i=0}^n\left\lfloor \frac{a\cdot i+b}{c} \right\rfloor \cdot i $
等会我们会看到这两个式子具有关联性。
-
case 1:\(a=0\)
\( \begin{aligned} &g\left( a,b,c,n \right) =\left\lfloor \frac{b}{c} \right\rfloor^2\cdot(n+1)\\ &h\left( a,b,c,n \right) =\left\lfloor \frac{b}{c} \right\rfloor\cdot \frac{n\cdot (n+1)}{2} \end{aligned} \) -
case 2:\(a\ge c {\kern 5pt} || {\kern 5pt} b\ge c\)
\[\begin{aligned} g\left( a,b,c,n \right) &=\sum_{i=0}^n\left\lfloor \frac{a\cdot i+b}{c} \right\rfloor^2 \\ &=\sum_{i=0}^n\left\lfloor \frac{(\left\lfloor \frac{a}{c} \right\rfloor \cdot c+a\%c)\cdot i+\left\lfloor \frac{b}{c} \right\rfloor\cdot c+b\%c}{c} \right\rfloor^2 \\ &=\sum_{i=0}^n\left( \left\lfloor \frac{a}{c} \right\rfloor\cdot i+\left\lfloor \frac{b}{c} \right\rfloor+\left\lfloor \frac{(a\%c)\cdot i+b\%c}{c} \right\rfloor \right)^2 \\ &=\left\lfloor \frac{a}{c} \right\rfloor^2\cdot \frac{n\cdot (n+1)\cdot (2n+1)}{6}+\left\lfloor \frac{a}{c} \right\rfloor\cdot \left\lfloor \frac{b}{c} \right\rfloor\cdot n\cdot \left( n+1 \right) + \left\lfloor \frac{b}{c} \right\rfloor^2\cdot (n+1) +\\ &{\kern 15pt}g\left( a\%c,b\%c,c,n \right)+2\cdot \left\lfloor \frac{a}{c} \right\rfloor\cdot h\left( a\%c,b\%c,c,n \right) +2\cdot \left\lfloor \frac{b}{c} \right\rfloor \cdot f\left( a\%c,b\%c,c,n \right) \\ h\left( a,b,c,n \right) &=\sum_{i=0}^n\left\lfloor \frac{a\cdot i+b}{c} \right\rfloor\cdot i \\ &=\sum_{i=0}^n\left\lfloor \frac{(\left\lfloor \frac{a}{c} \right\rfloor \cdot c+a\%c)\cdot i+\left\lfloor \frac{b}{c} \right\rfloor\cdot c+b\%c}{c} \right\rfloor\cdot i \\ &=\left\lfloor \frac{a}{c} \right\rfloor\cdot \frac{n\cdot (n+1)\cdot (2n+1)}{6}+\left\lfloor \frac{b}{c} \right\rfloor\cdot \frac{n\cdot (n+1)}{2}+h\left( a\%c,b\%c,c,n \right) \end{aligned} \] -
case 3:\(a < c {\kern 5pt} \&\& {\kern 5pt} b < c\)
\[\begin{aligned} g\left( a,b,c,n \right) &=\sum_{i=1}^n\left\lfloor \frac{a\cdot i+b}{c} \right\rfloor^2 \\ &=\sum_{k=0}^{\left\lfloor \frac{a\cdot n+b}{c} \right\rfloor-1}\left( \left\lfloor \frac{c\cdot (k+1)-b+a-1}{a} \right\rfloor-1-\left\lfloor \frac{k\cdot c-b+a-1}{a} \right\rfloor+1\right)\cdot k^2+ \\ &{\kern 15pt}\left( n-\left\lfloor \frac{\left\lfloor \frac{a\cdot n+b}{c} \right\rfloor\cdot c-b+a-1}{a} \right\rfloor+1 \right)\cdot \left\lfloor \frac{a\cdot n+b}{c} \right\rfloor^2 \\ &=\sum_{k=1}^{\left\lfloor \frac{a\cdot n+b}{c} \right\rfloor}\left\lfloor \frac{c\cdot k-b-1}{a} \right\rfloor \cdot k^2-\sum_{k=0}^{\left\lfloor \frac{a\cdot n+b}{c} \right\rfloor-1} \left\lfloor \frac{c\cdot k-b-1}{a} \right\rfloor \cdot k^2-\sum_{k=0}^{\left\lfloor \frac{a\cdot n+b}{c} \right\rfloor-1}\left\lfloor \frac{c\cdot (k+1)-b-1}{a} \right\rfloor-\\ &{\kern 15pt}\sum_{k=0}^{\left\lfloor \frac{a\cdot n+b}{c} \right\rfloor-1}2k\cdot \left\lfloor \frac{c\cdot (k+1)-b-1}{a} \right\rfloor+\left( n-\left\lfloor \frac{\left\lfloor \frac{a\cdot n+b}{c} \right\rfloor\cdot c-b-1}{a} \right\rfloor \right)\cdot \left\lfloor \frac{a\cdot n+b}{c} \right\rfloor^2 \\ &=\left\lfloor\frac{a\cdot n+b}{c}\right\rfloor^2\cdot n-f\left( c,c-b-1,a, \left\lfloor\frac{a\cdot n+b}{c}\right\rfloor-1\right)-2\cdot h\left( c,c-b-1,a, \left\lfloor\frac{a\cdot n+b}{c}\right\rfloor-1\right) \\ h\left( a,b,c,n \right) &=\sum_{i=0}^n\left\lfloor \frac{a\cdot i+b}{c} \right\rfloor \cdot i \\ &=\sum_{k=0}^{\left\lfloor \frac{a\cdot n+b}{c} \right\rfloor-1}\frac{k}{2}\cdot \left( \left\lfloor \frac{c\cdot (k+1)-b-1}{a} \right\rfloor -\left\lfloor \frac{c\cdot k-b-1}{a} \right\rfloor\right)\cdot \left( \left\lfloor \frac{c\cdot (k+1)-b-1}{a} \right\rfloor+\left\lfloor \frac{c\cdot k-b-1}{a} \right\rfloor+1 \right) + \\ &{\kern 15pt}\frac{1}{2}\cdot \left\lfloor \frac{n\cdot a+b}{c} \right\rfloor\cdot \left( n-\left\lfloor \frac{\left\lfloor \frac{n\cdot a+b}{c} \right\rfloor\cdot c-b-1}{a} \right\rfloor\right) \cdot \left( n+\left\lfloor \frac{\left\lfloor \frac{n\cdot a+b}{c} \right\rfloor\cdot c-b-1}{a} \right\rfloor+1 \right) \\ &=\frac{1}{2}\cdot \sum_{i=0}^{\left\lfloor \frac{n\cdot a+b}{c} \right\rfloor-1}i\cdot \left( \left\lfloor \frac{c\cdot (i+1)-b-1}{a} \right\rfloor^2-\left\lfloor \frac{c\cdot i-b-1}{a} \right\rfloor^2 \right) + \frac{1}{2}\cdot \sum_{i=0}^{\left\lfloor \frac{n\cdot a+b}{c} \right\rfloor-1}i\cdot \left( \left\lfloor \frac{c\cdot (i+1)-b-1}{a} \right\rfloor-\left\lfloor \frac{c\cdot i-b-1}{a} \right\rfloor \right) \\ &{\kern 15pt} \frac{1}{2}\cdot \left\lfloor \frac{n\cdot a+b}{c} \right\rfloor\cdot \left( n-\left\lfloor \frac{\left\lfloor \frac{n\cdot a+b}{c} \right\rfloor\cdot c-b-1}{a} \right\rfloor\right) \cdot \left( n+\left\lfloor \frac{\left\lfloor \frac{n\cdot a+b}{c} \right\rfloor\cdot c-b-1}{a} \right\rfloor+1 \right) \\ &=\left\lfloor \frac{n\cdot a+b}{c} \right\rfloor\cdot \frac{n\cdot (n+1)}{2}-\frac{1}{2}\cdot g\left( c,c-b-1,a, \left\lfloor\frac{a\cdot n+b}{c}\right\rfloor-1\right) - \frac{1}{2}\cdot f\left( c,c-b-1,a, \left\lfloor\frac{a\cdot n+b}{c}\right\rfloor-1\right) \end{aligned} \]
综上,
code:P5170 【模板】类欧几里得算法
#include <cstdio>
#include <iostream>
using namespace std;
const int mo = 998244353;
struct Mint {
int a;
Mint() {}
Mint(int o) { a = o; }
Mint operator+(const Mint& o) const { return (a + o.a) % mo; }
Mint operator+(const int& o) const { return (o + a) % mo; }
Mint operator-(const Mint& o) const {
return Mint(((a - o.a) % mo) + mo) % mo;
}
Mint operator*(const Mint& o) const { return Mint(1ll * a * o.a % mo); }
Mint operator/(const Mint& o) const { return Mint(a / o.a); }
operator int() { return a; }
};
struct func {
Mint f, g, h;
func() {}
func(Mint o, Mint p, Mint q) {
f = o;
g = p;
h = q;
}
};
const Mint inv2 = Mint((mo + 1) >> 1);
const Mint inv3 = Mint((mo + 1) / 3);
const Mint inv6 = Mint(inv2 * inv3);
func calc(int A, int B, int C, int N) {
Mint a = A;
Mint b = B;
Mint c = C;
Mint n = N;
if (!A) {
return func((b / c) * (n + 1), (b / c) * (b / c) * (n + 1),
(b / c) * n * (n + 1) * inv2);
}
func ans;
if (A >= C || B >= C) {
ans = calc(A % C, B % C, C, N);
return func((a / c) * n * (n + 1) * inv2 + (b / c) * (n + 1) + ans.f,
n * (n + 1) * (n + n + 1) * inv6 * (a / c) * (a / c) +
(a / c) * (b / c) * n * (n + 1) +
(b / c) * (b / c) * (n + 1) + ans.g +
(a / c) * ans.h * Mint(2) + (b / c) * ans.f * Mint(2),
(a / c) * n * (n + 1) * (n + n + 1) * inv6 +
(b / c) * n * (n + 1) * inv2 + ans.h);
}
int m = (1ll * A * N + B) / C;
Mint M = Mint(m);
ans = calc(C, C - B - 1, A, m - 1);
return func(M * n - ans.f, n * M * M - ans.h * Mint(2) - ans.f,
M * n * n * inv2 + M * n * inv2 - ans.g * inv2 - ans.f * inv2);
}
int main() {
int T;
cin >> T;
while (T--) {
int a, b, c, n;
scanf("%d%d%d%d", &n, &a, &b, &c);
func ans = calc(a, b, c, n);
printf("%d %d %d\n", ans.f, ans.g, ans.h);
}
return 0;
}