类欧几里得算法

我们要快速求以下函数的值:

f(a,b,c,n)=∑i=0n⌊ai+bc⌋f(a,b,c,n)=\sum_{i=0}^n \lfloor \frac{ai+b}{c} \rfloor

g(a,b,c,n)=∑i=0ni⌊ai+bc⌋g(a,b,c,n)=\sum_{i=0}^n i \lfloor \frac{ai+b}{c} \rfloor

h(a,b,c,n)=∑i=0n⌊ai+bc⌋2h(a,b,c,n)=\sum_{i=0}^n \lfloor \frac{ai+b}{c} \rfloor^2

f

先考虑 a≥ca\ge c 或 b≥cb\ge c 的情况。我们考虑将 aa 和 bb 对 cc 取模。

f(a,b,c,n)=∑i=0n⌊ai+bc⌋=∑i=0n⌊(a mod c)i+b mod cc⌋+i⌊ac⌋+⌊bc⌋=(∑i=0n⌊(a mod c)i+b mod cc⌋)+(∑i=0ni⌊ac⌋)+(∑i=0n⌊bc⌋)=f(a mod c,b mod c,c,n)+n(n+1)2⌊ac⌋+(n+1)⌊bc⌋\begin{aligned} f(a,b,c,n)&=\sum_{i=0}^n \lfloor \frac{ai+b}{c} \rfloor\\ &=\sum_{i=0}^n\lfloor \frac{(a \bmod c)i+b\bmod c}{c} \rfloor+i\lfloor \frac{a}{c} \rfloor+\lfloor \frac{b}{c} \rfloor\\ &=(\sum_{i=0}^n \lfloor \frac{(a \bmod c)i+b\bmod c}{c} \rfloor)+(\sum_{i=0}^ni\lfloor \frac{a}{c} \rfloor)+(\sum_{i=0}^n\lfloor \frac{b}{c} \rfloor)\\ &=f(a\bmod c,b\bmod c,c,n)+\frac{n(n+1)}{2}\lfloor \frac{a}{c} \rfloor+(n+1)\lfloor \frac{b}{c} \rfloor \end{aligned}

此时 aa 变为 a mod ca\bmod c,bb 变为 b mod cb\bmod c。我们接下来考虑 a<c,b<ca<c,b<c 的情况。设 m=⌊an+bc⌋m=\lfloor \frac{an+b}{c} \rfloor,则

f(a,b,c,n)=∑i=0n⌊ai+bc⌋=∑i=0n∑j=0⌊ai+bc⌋−11=∑i=0n∑j=0m−1[j<⌊ai+bc⌋]=∑j=0m−1∑i=0n[j<⌊ai+bc⌋]\begin{aligned} f(a,b,c,n)&=\sum_{i=0}^n \lfloor \frac{ai+b}{c} \rfloor\\ &=\sum_{i=0}^n \sum_{j=0}^{\lfloor \frac{ai+b}{c} \rfloor-1} 1\\ &=\sum_{i=0}^n \sum_{j=0}^{m-1} [j<\lfloor \frac{ai+b}{c} \rfloor]\\ &=\sum_{j=0}^{m-1} \sum_{i=0}^n [j<\lfloor \frac{ai+b}{c} \rfloor]\\ \end{aligned}

我们推导 [j<⌊ai+bc⌋][j<\lfloor \frac{ai+b}{c} \rfloor] 的值:

j<⌊ai+bc⌋  ⟺  j+1≤⌊ai+bc⌋  ⟺  j+1≤ai+bc  ⟺  ai≥cj+c−b  ⟺  ai>cj+c−b−1  ⟺  i>⌊cj+c−b−1a⌋\begin{aligned} j<\lfloor \frac{ai+b}{c} \rfloor & \iff j+1\le\lfloor \frac{ai+b}{c} \rfloor \\ &\iff j+1\le \frac{ai+b}{c} \\ &\iff ai\ge cj+c-b \\ &\iff ai> cj+c-b-1 \\ &\iff i> \lfloor\frac{cj+c-b-1}{a}\rfloor \end{aligned}

所以 [j<⌊ai+bc⌋]=[i>⌊cj+c−b−1a⌋][j<\lfloor \frac{ai+b}{c} \rfloor]=[i> \lfloor\frac{cj+c-b-1}{a}\rfloor]。我们继续推导:

f(a,b,c,n)=∑j=0m−1∑i=0n[j<⌊ai+bc⌋]=∑j=0m−1∑i=0n[i>⌊cj+c−b−1a⌋]=∑j=0m−1n−⌊cj+c−b−1a⌋=nm−∑j=0m−1⌊cj+c−b−1a⌋=nm−f(c,c−b−1,a,m−1)\begin{aligned} f(a,b,c,n)&=\sum_{j=0}^{m-1} \sum_{i=0}^n [j<\lfloor \frac{ai+b}{c} \rfloor]\\ &=\sum_{j=0}^{m-1} \sum_{i=0}^n [i> \lfloor\frac{cj+c-b-1}{a}\rfloor]\\ &=\sum_{j=0}^{m-1} n-\lfloor\frac{cj+c-b-1}{a}\rfloor\\ &=nm-\sum_{j=0}^{m-1} \lfloor\frac{cj+c-b-1}{a}\rfloor\\ &=nm-f(c,c-b-1,a,m-1) \end{aligned}

最后,边界情况是 a=0a=0。显然此时 f(a,b,c,n)=(n+1)⌊bc⌋f(a,b,c,n)=(n+1)\lfloor \frac{b}{c} \rfloor。综上:

f(a,b,c,n)={f(a mod c,b mod c,c,n)+n(n+1)2⌊ac⌋+(n+1)⌊bc⌋a≥c或b≥cnm−f(c,c−b−1,a,m−1)a<c,b<c(n+1)⌊bc⌋a=0f(a,b,c,n)=\begin{cases} f(a\bmod c,b\bmod c,c,n)+\frac{n(n+1)}{2}\lfloor \frac{a}{c} \rfloor+(n+1)\lfloor \frac{b}{c} \rfloor & a\ge c 或 b\ge c \\ nm-f(c,c-b-1,a,m-1) & a<c,b<c \\ (n+1)\lfloor \frac{b}{c} \rfloor & a=0 \\ \end{cases}

我们观察式子中 a,ca,c 位置上的变化。在第一个式子中,aa 对 cc 取模。在第二个式子中,a,ca,c 交换了位置。这样交替进行,直到 a=0a=0 的过程,与欧几里得算法中辗转相除的过程相同。因此直接递归的时间复杂度是 O(log⁡n)O(\log n)。

g

接下来的推推导过程与 ff 类似,但是复杂了很多。

先考虑 a≥ca\ge c 或 b≥cb\ge c 的情况

g(a,b,c,n)=∑i=0ni⌊ai+bc⌋=∑i=0ni(⌊(a mod c)i+b mod cc⌋+i⌊ac⌋+⌊bc⌋)=(∑i=0ni⌊(a mod c)i+b mod cc⌋)+(∑i=0ni2⌊ac⌋)+(∑i=0ni⌊bc⌋)=g(a mod c,b mod c,c,n)+n(n+1)(2n+1)6⌊ac⌋+n(n+1)2⌊bc⌋\begin{aligned} g(a,b,c,n)&=\sum_{i=0}^n i \lfloor \frac{ai+b}{c} \rfloor\\ &=\sum_{i=0}^n i(\lfloor \frac{(a \bmod c)i+b\bmod c}{c} \rfloor+i\lfloor \frac{a}{c} \rfloor+\lfloor \frac{b}{c} \rfloor)\\ &=(\sum_{i=0}^n i\lfloor \frac{(a \bmod c)i+b\bmod c}{c} \rfloor)+(\sum_{i=0}^ni^2\lfloor \frac{a}{c} \rfloor)+(\sum_{i=0}^n i\lfloor \frac{b}{c} \rfloor)\\ &=g(a\bmod c,b\bmod c,c,n)+\frac{n(n+1)(2n+1)}{6}\lfloor \frac{a}{c} \rfloor+\frac{n(n+1)}{2}\lfloor \frac{b}{c} \rfloor \end{aligned}

然后考虑 a<c,b<ca<c,b<c 的情况。省略了一些在推导 ff 时推导过的东西。

g(a,b,c,n)=∑i=0ni⌊ai+bc⌋=∑j=0m−1∑i=0ni×[i>⌊cj+c−b−1a⌋]=∑j=0m−1∑i=⌊cj+c−b−1a⌋+1ni\begin{aligned} g(a,b,c,n)&=\sum_{i=0}^n i \lfloor \frac{ai+b}{c} \rfloor\\ &=\sum_{j=0}^{m-1} \sum_{i=0}^n i\times[i> \lfloor\frac{cj+c-b-1}{a}\rfloor]\\ &=\sum_{j=0}^{m-1} \sum_{i=\lfloor\frac{cj+c-b-1}{a}\rfloor+1}^n i\\ \end{aligned}

我们设 t=⌊cj+c−b−1a⌋t=\lfloor\frac{cj+c-b-1}{a}\rfloor。继续推导

g(a,b,c,n)=∑j=0m−1∑i=t+1ni=∑j=0m−1(t+1+n)(n−t)2=∑j=0m−1(n2+n)−(t2+t)2=12∑j=0m−1(n2+n)−(t2+t)=12[nm(n+1)−∑j=0m−1⌊cj+c−b−1a⌋2−∑j=0m−1⌊cj+c−b−1a⌋]=12[nm(n+1)−h(c,c−b−1,a,m−1)−f(c,c−b−1,a,m−1)]\begin{aligned} g(a,b,c,n)&=\sum_{j=0}^{m-1} \sum_{i=t+1}^n i\\ &=\sum_{j=0}^{m-1}\frac{(t+1+n)(n-t)}{2}\\ &=\sum_{j=0}^{m-1}\frac{(n^2+n)-(t^2+t)}{2}\\ &=\frac{1}{2}\sum_{j=0}^{m-1}(n^2+n)-(t^2+t)\\ &=\frac{1}{2}[nm(n+1)-\sum_{j=0}^{m-1}\lfloor\frac{cj+c-b-1}{a}\rfloor^2-\sum_{j=0}^{m-1}\lfloor\frac{cj+c-b-1}{a}\rfloor]\\ &=\frac{1}{2}[nm(n+1)-h(c,c-b-1,a,m-1)-f(c,c-b-1,a,m-1)]\\ \end{aligned}

最后考虑边界情况 a=0a=0。显然此时 g(a,b,c,n)=n(n+1)2⌊bc⌋g(a,b,c,n)=\frac{n(n+1)}{2}\lfloor \frac{b}{c} \rfloor。综上:

g(a,b,c,n)={g(a mod c,b mod c,c,n)+n(n+1)(2n+1)6⌊ac⌋+n(n+1)2⌊bc⌋a≥c或b≥c12[nm(n+1)−h(c,c−b−1,a,m−1)−f(c,c−b−1,a,m−1)]a<c,b<cn(n+1)2⌊bc⌋a=0g(a,b,c,n)=\begin{cases} g(a\bmod c,b\bmod c,c,n)+\frac{n(n+1)(2n+1)}{6}\lfloor \frac{a}{c} \rfloor+\frac{n(n+1)}{2}\lfloor \frac{b}{c} \rfloor & a\ge c 或 b\ge c \\ \frac{1}{2}[nm(n+1)-h(c,c-b-1,a,m-1)-f(c,c-b-1,a,m-1)] & a<c,b<c \\ \frac{n(n+1)}{2}\lfloor \frac{b}{c} \rfloor & a=0 \\ \end{cases}

h

先考虑 a≥ca\ge c 或 b≥cb\ge c 的情况

h(a,b,c,n)=∑i=0n⌊ai+bc⌋2=∑i=0n(⌊(a mod c)i+b mod cc⌋+i⌊ac⌋+⌊bc⌋)2=∑i=0n⌊(a mod c)i+b mod cc⌋2+(i⌊ac⌋)2+⌊bc⌋2+2i⌊(a mod c)i+b mod cc⌋⌊ac⌋+2⌊(a mod c)i+b mod cc⌋⌊bc⌋+2i⌊ac⌋⌊bc⌋=h(a mod c,b mod c,c,n)+n(n+1)(2n+1)6⌊ac⌋2+(n+1)⌊bc⌋2+2g(a mod c,b mod c,c,n)⌊ac⌋+2f(a mod c,b mod c,c,n)⌊bc⌋+n(n+1)⌊ac⌋⌊bc⌋\begin{aligned} h(a,b,c,n)&=\sum_{i=0}^n \lfloor \frac{ai+b}{c} \rfloor^2\\ &=\sum_{i=0}^n (\lfloor \frac{(a \bmod c)i+b\bmod c}{c} \rfloor+i\lfloor \frac{a}{c} \rfloor+\lfloor \frac{b}{c} \rfloor)^2\\ &=\sum_{i=0}^n \lfloor \frac{(a \bmod c)i+b\bmod c}{c} \rfloor^2+(i\lfloor \frac{a}{c} \rfloor)^2+\lfloor \frac{b}{c} \rfloor^2+2i\lfloor \frac{(a \bmod c)i+b\bmod c}{c} \rfloor\lfloor \frac{a}{c} \rfloor+2\lfloor \frac{(a \bmod c)i+b\bmod c}{c} \rfloor\lfloor \frac{b}{c} \rfloor+2i\lfloor \frac{a}{c} \rfloor\lfloor \frac{b}{c} \rfloor\\ &=h(a\bmod c,b \bmod c,c,n)+\frac{n(n+1)(2n+1)}{6}\lfloor \frac{a}{c} \rfloor^2+(n+1)\lfloor \frac{b}{c} \rfloor^2+2g(a\bmod c,b \bmod c,c,n)\lfloor \frac{a}{c} \rfloor+2f(a\bmod c,b \bmod c,c,n) \lfloor \frac{b}{c} \rfloor+n(n+1)\lfloor \frac{a}{c} \rfloor\lfloor \frac{b}{c} \rfloor \end{aligned}

整理得:

h(a,b,c,n)=h(a mod c,b mod c,c,n)+2f(a mod c,b mod c,c,n)⌊bc⌋+2g(a mod c,b mod c,c,n)⌊ac⌋+n(n+1)(2n+1)6⌊ac⌋2+(n+1)⌊bc⌋2+n(n+1)⌊ac⌋⌊bc⌋h(a,b,c,n)=h(a\bmod c,b \bmod c,c,n)+2f(a\bmod c,b \bmod c,c,n) \lfloor \frac{b}{c} \rfloor+2g(a\bmod c,b \bmod c,c,n)\lfloor \frac{a}{c} \rfloor+\frac{n(n+1)(2n+1)}{6}\lfloor \frac{a}{c} \rfloor^2+(n+1)\lfloor \frac{b}{c} \rfloor^2+n(n+1)\lfloor \frac{a}{c} \rfloor\lfloor \frac{b}{c} \rfloor

然后考虑 a<c,b<ca<c,b<c 的情况。平方不太好处理,我们考虑平方分成两个部分。

n2=2n(n+1)2−n=2∑i=1ni−nn^2=2\frac{n(n+1)}{2}-n=2\sum_{i=1}^ni-n

所以:

h(a,b,c,n)=∑i=0n⌊ai+bc⌋2=∑i=0n[(2∑j=1⌊ai+bc⌋j)−⌊ai+bc⌋2]=(2∑i=0n∑j=1⌊ai+bc⌋j)−f(a,b,c,n)\begin{aligned} h(a,b,c,n)&=\sum_{i=0}^n \lfloor \frac{ai+b}{c} \rfloor^2\\ &=\sum_{i=0}^n\left[\left(2\sum_{j=1}^{\lfloor \frac{ai+b}{c} \rfloor}j\right)-\lfloor \frac{ai+b}{c} \rfloor^2\right]\\ &=\left(2\sum_{i=0}^n\sum_{j=1}^{\lfloor \frac{ai+b}{c} \rfloor}j\right)-f(a,b,c,n) \end{aligned}

我们接着推导式子的前半部分:

∑i=0n∑j=1⌊ai+bc⌋j=∑i=0n∑j=0⌊ai+bc⌋−1j+1=∑j=0m−1(j+1)∑i=0n[j<⌊ai+bc⌋]=∑j=0m−1(j+1)∑i=0n[i>⌊cj+c−b−1a⌋]=∑j=0m−1(j+1)(n−⌊cj+c−b−1a⌋)=∑j=0m−1jn+n−⌊cj+c−b−1a⌋−j⌊cj+c−b−1a⌋=nm(m−1)2+nm−f(c,c−b−1,a,m−1)−g(c,c−b−1,a,m−1)=nm(m+1)2−f(c,c−b−1,a,m−1)−g(c,c−b−1,a,m−1)\begin{aligned} \sum_{i=0}^n\sum_{j=1}^{\lfloor \frac{ai+b}{c} \rfloor}j&=\sum_{i=0}^n\sum_{j=0}^{\lfloor \frac{ai+b}{c} \rfloor-1}j+1\\ &=\sum_{j=0}^{m-1}(j+1)\sum_{i=0}^n[j<\lfloor \frac{ai+b}{c} \rfloor]\\ &=\sum_{j=0}^{m-1}(j+1)\sum_{i=0}^n[i> \lfloor\frac{cj+c-b-1}{a}\rfloor]\\ &=\sum_{j=0}^{m-1}(j+1)(n-\lfloor\frac{cj+c-b-1}{a}\rfloor)\\ &=\sum_{j=0}^{m-1}jn+n-\lfloor\frac{cj+c-b-1}{a}\rfloor-j\lfloor\frac{cj+c-b-1}{a}\rfloor\\ &=\frac{nm(m-1)}{2}+nm-f(c,c-b-1,a,m-1)-g(c,c-b-1,a,m-1)\\ &=\frac{nm(m+1)}{2}-f(c,c-b-1,a,m-1)-g(c,c-b-1,a,m-1)\\ \end{aligned}

带入到原式,得

h(a,b,c,n)=(2∑i=0n∑j=1⌊ai+bc⌋j)−f(a,b,c,n)=nm(m+1)−2f(c,c−b−1,a,m−1)−2g(c,c−b−1,a,m−1)−f(a,b,c,n)\begin{aligned} h(a,b,c,n)&=\left(2\sum_{i=0}^n\sum_{j=1}^{\lfloor \frac{ai+b}{c} \rfloor}j\right)-f(a,b,c,n)\\ &=nm(m+1)-2f(c,c-b-1,a,m-1)-2g(c,c-b-1,a,m-1)-f(a,b,c,n) \end{aligned}

最后考虑边界情况 a=0a=0。显然此时 h(a,b,c,n)=(n+1)⌊bc⌋2h(a,b,c,n)=(n+1)\lfloor \frac{b}{c} \rfloor^2。综上:

h(a,b,c,n)={h(a mod c,b mod c,c,n)+2f(a mod c,b mod c,c,n)⌊bc⌋+2g(a mod c,b mod c,c,n)⌊ac⌋+n(n+1)(2n+1)6⌊ac⌋2+(n+1)⌊bc⌋2+n(n+1)⌊ac⌋⌊bc⌋a≥c或b≥cnm(m+1)−2f(c,c−b−1,a,m−1)−2g(c,c−b−1,a,m−1)−f(a,b,c,n)a<c,b<c(n+1)⌊bc⌋2a=0h(a,b,c,n)=\begin{cases} h(a\bmod c,b \bmod c,c,n)+2f(a\bmod c,b \bmod c,c,n) \lfloor \frac{b}{c} \rfloor+2g(a\bmod c,b \bmod c,c,n)\lfloor \frac{a}{c} \rfloor+\frac{n(n+1)(2n+1)}{6}\lfloor \frac{a}{c} \rfloor^2+(n+1)\lfloor \frac{b}{c} \rfloor^2+n(n+1)\lfloor \frac{a}{c} \rfloor\lfloor \frac{b}{c} \rfloor & a\ge c 或 b\ge c \\ nm(m+1)-2f(c,c-b-1,a,m-1)-2g(c,c-b-1,a,m-1)-f(a,b,c,n) & a<c,b<c \\ (n+1)\lfloor \frac{b}{c} \rfloor^2 & a=0 \\ \end{cases}

实现

如果 f,g,hf,g,h 分开实现,时间复杂度会无法保证。例如,在求 g(a,b,c,n)g(a,b,c,n) 时,如果满足 a<c,b<ca<c,b<c,那么程序会同时调用 ff 和 hh,导致递归形成很多分支,时间复杂度也就无法保证。

所以我们将 f,g,hf,g,h 放在同一个函数实现。代码没有任何难度,抄上面的公式即可。公式很复杂,注意不要抄错了。

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
const int mod = 998244353, inv2 = 499122177, inv6 = 166374059;
struct S
{
ll f, g, h;
S(ll f, ll g, ll h) : f(f), g(g), h(h) {}
};
S solve(ll a, ll b, ll c, ll n)
{
if (a == 0) return S((n + 1) * (b / c) % mod, n * (n + 1) / 2 % mod * (b / c) % mod, (n + 1) * (b / c) % mod * (b / c) % mod);
if (a >= c || b >= c)
{
S x = solve(a % c, b % c, c, n);
ll f = (x.f + n * (n + 1) / 2 % mod * (a / c) % mod + (n + 1) * (b / c) % mod) % mod;
ll g = (x.g + (n * (n + 1) % mod * (2 * n + 1) % mod * inv6 % mod) * (a / c) % mod + n * (n + 1) / 2 % mod * (b / c) % mod) % mod;
ll h = (x.h + 2 * x.f % mod * (b / c) % mod + 2 * x.g % mod * (a / c) % mod + (n * (n + 1) % mod * (2 * n + 1) % mod * inv6 % mod) * (a / c) % mod * (a / c) % mod + (n + 1) * (b / c) % mod * (b / c) % mod + n * (n + 1) % mod * (a / c) % mod * (b / c) % mod) % mod;
return S(f, g, h);
}
else
{
ll m = (a * n + b) / c;
S x = solve(c, c - b - 1, a, m - 1);
ll f = (n * m % mod - x.f + mod) % mod;
ll g = ((m * n % mod * (n + 1) % mod - x.h - x.f) % mod + mod) % mod * inv2 % mod;
ll h = ((n * m % mod * (m + 1) % mod - 2 * x.f - 2 * x.g - f) % mod + mod) % mod;
return S(f, g, h);
}
}