类欧几里得算法抄式子笔记

本文是以 oi-wiki 为基础,自己手 $\LaTeX$ 整理的式子;和本博客、oi-wiki 原文一样遵循 CC BY-SA 4.0 协议

洛谷板题【模板】类欧几里得算法

其中 $a, b, c, n$ 是常数。需要一个 $O(\log n)$ 的算法。

若 $a \ge c$ 或者 $b \ge c$,则可以将 $a$ 或 $b$ 对 $c$ 取模以简化问题:

那么问题转化为了 $a < c, b < c$ 的情况。令 $m = \lfloor (an + b) / c\rfloor, t = \lfloor (cj + c - b - 1) / a \rfloor$,则

复杂度为 $O(\log n)$。


令 $m = \lfloor (an + b) / c\rfloor, t = \lfloor (cj + c - b - 1) / a \rfloor$,则


令 $m = \lfloor (an + b) / c\rfloor, t = \lfloor (cj + c - b - 1) / a \rfloor$。又有


三个函数一起递归计算,总复杂度 $O(\log n)$。


关于代码,由于我过懒,想用不定参解决,于是研究了 c++ 的不定参写法,浪费了更多时间。

板题最终代码(全是式子,看看就行,注意询问顺序 $f, h, g$):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
using ll = long long;

constexpr int mod = 998244353, inv2 = 499122177, inv6 = 166374059;

int Add(ll t) {
return (t % mod + mod) % mod;
}

template<typename... Ts>
int Add(ll t, Ts... r) {
return ((t + Add(r...)) % mod + mod) % mod;
}

int Mul(ll t) {
return t % mod;
}

template<typename... Ts>
int Mul(ll t, Ts... r) {
return (t * Mul(r...)) % mod;
}

struct Node {
int f, g, h;

Node() {}

Node(int F, int G, int H): f(F), g(G), h(H) {}
};

Node solve(ll N, int a, int b, int c) {
int fac = a / c, fbc = b / c;
ll m = (1ll * a * N + b) / c, Np = N + 1, N2p = N << 1 | 1;
if (!a) return Node(Mul(fbc, Np), Mul(fbc, N, Np, inv2), Mul(fbc, fbc, Np));

Node z, y;
if (a >= c || b >= c) {
z.f = Add(Mul(N, Np, inv2, fac), Mul(fbc, Np));
z.g = Add(Mul(fac, N, Np, N2p, inv6), Mul(fbc, N, Np, inv2));
z.h = Add(Mul(fac, fac, N, Np, N2p, inv6), Mul(fbc, fbc, Np), Mul(fac, fbc, N, Np));
y = solve(N, a % c, b % c, c);
z.f = Add(z.f, y.f);
z.g = Add(z.g, y.g);
z.h = Add(z.h, y.h, Mul(2, fbc, y.f), Mul(2, fac, y.g));
return z;
}

y = solve(m - 1, c, c - b - 1, a);
z.f = Add(Mul(N, m), -y.f);
z.g = Mul(Add(Mul(N, m, Np), -y.f, -y.h), inv2);
z.h = Add(Mul(N, m, m + 1), -2 * y.g, -2 * y.f, -z.f);
return z;
}

int main() {
int T;
Node ans;

cin >> T;
for (int N, a, b, c; T; --T) {
cin >> N >> a >> b >> c;
ans = solve(N, a, b, c);
cout << ans.f << ' ' << ans.h << ' ' << ans.g << '\n';
}
return 0;
}

文章作者: fa_555
文章链接: https://blog.fa555.tech/2020/%E7%B1%BB%E6%AC%A7%E5%87%A0%E9%87%8C%E5%BE%97%E7%AE%97%E6%B3%95%E6%8A%84%E5%BC%8F%E5%AD%90%E7%AC%94%E8%AE%B0/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 fa_555's Blog