Prologue
大家都知道,求 \(\gcd\) 的方法叫辗转相除法,又称欧几里得算法,它的思想大概就是把 \(f(a,b)\) 的值通过 \(f(b,a\bmod b)\) 来转移,从而达到 \(O(\log n)\) 的复杂度。
类欧几里得算法(类欧)也是运用了这个思想,但除此之外与 \(\gcd\) 并没有什么联系(
Intro
给定正整数 \(n,a,b,c(0\le a,b,c,n \le 10^{9})\),求 \(f(a,b,c,n) = \sum\limits_{i=0}^n\lfloor\frac{ai+b}{c}\rfloor\)。
看见取整符号第一感觉当然是整除分块,然而似乎整除分块做不了。
首先考虑 \(a=0\) 的情况,此时显然有 \(f(a,b,c,n)=(n+1)\lfloor\frac{b}{c}\rfloor\)。
然后考虑 \(a \ge c,b \ge c\) 的情况,把 \(a,b\) 都转移成小于 \(c\) 的数。
我们知道,对于正整数 \(x,y\),有 \(x = \lfloor\frac{x}{y}\rfloor y+(x \bmod y)\)。于是我们把原式展开可以得到:
\[\begin{aligned}
f(a,b,c,n) = &\ \sum\limits_{i=0}^n\lfloor\frac{ai+b}{c}\rfloor\\
= &\ \sum\limits_{i=0}^n\lfloor\frac{(\lfloor\frac{a}{c}\rfloor c+(a \bmod c))i+(\lfloor\frac{b}{c}\rfloor c+(b \bmod c))}{c}\rfloor\\
= &\ \sum\limits_{i=0}^n\lfloor\frac{(a \bmod c)i+(b \bmod c)}{c}\rfloor+\lfloor\frac{a}{c}\rfloor i+\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}
\]
剩下 \(a<c,b<c\) 时的情况。注意到原式里只有 \(i\) 一个变量,考虑变换一下计算 \(i\) 贡献的方式:
\[\begin{aligned}
f(a,b,c,n) = &\ \sum\limits_{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_{j=0}^{\lfloor\frac{an+b}{c}\rfloor-1}\sum_{i=0}^n[j < \lfloor\frac{ai+b}{c}\rfloor]\\
\end{aligned}
\]
然后这个不等式是不是看着很不爽,我们把它变换一下:
\[j < \lfloor\frac{ai+b}{c}\rfloor\\
j+1\le \frac{ai+b}{c}\\
cj+c\le ai+b\\
cj+c-b-1<ai\\
i > \lfloor\frac{cj+c-b-1}{a}\rfloor
\]
再令 \(m=\lfloor\frac{an+b}{c}\rfloor\),于是原式就可以化为:
\[\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)\\
= &\ mn-f(c,c-b-1,a,m-1)
\end{aligned}
\]
此时我们发现 \(a,c\) 互换了位置,于是可以递归下去,按照辗转相除的思想进行处理。总结下来就是这样:
\[f(a,b,c,n)=\left\{
\begin{array}{lr}
(n+1)\lfloor\frac{b}{c}\rfloor & a=0\\
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\\
mn-f(c,c-b-1,a,m-1) & \text{otherwise}
\end{array}
\right.
\]
时间复杂度显然与 \(\gcd\) 相同,为 \(O(\log (a+c))\)。
Extend
给定 \(n,a,b,c\),求:
\[g(a,b,c,n) = \sum_{i=0}^n\lfloor\frac{ai+b}{c}\rfloor^2\\h(a,b,c,n)=\sum_{i=0}^ni\lfloor\frac{ai+b}{c}\rfloor
\]
\(g\) 的推导
当 \(a=0\) 时,显然有 \(g(a,b,c,n)=(n+1)\lfloor\frac b c\rfloor^2\)。
当 \(a\ge c,b \ge c\) 时:
\[g(a,b,c,n)=g(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+\\
2h(a\bmod c,b\bmod c,c,n)\lfloor\frac{a}{c}\rfloor+n(n+1)\lfloor\frac{a}{c}\rfloor\lfloor\frac b c\rfloor+2f(a\bmod c,b\bmod c,c,n)\lfloor\frac b c\rfloor
\]
\(g\) 取模的推导过程
然后考虑 \(a<c,b<c\) 的情况。令 \(m=\lfloor\frac{an+b}{c}\rfloor,t=\lfloor\frac{cj+c-b-1}{a}\rfloor\)。于是有:
\[\begin{aligned}
g(a,b,c,n) = &\ \sum_{i=0}^n\lfloor\frac{ai+b}c\rfloor^2\\
= &\ \sum_{i=0}^n\left(2(\sum_{j=0}^{\lfloor\frac{ai+b}c\rfloor}j)-{\lfloor\frac{ai+b}c\rfloor}\right)\\
= &\ \left(2\sum_{i=0}^n\sum_{j=0}^{\lfloor\frac{ai+b}c\rfloor}j\right)-f(a,b,c,n)\\
\end{aligned}
\]
然后化简一下左边那玩意:
\[\begin{aligned}
\sum_{i=0}^n\sum_{j=0}^{\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>t]\\
= &\ \sum_{j=0}^{m-1}(j+1)(n-t)\\
= &\ \sum_{j=0}^{m}jn-\sum_{j=0}^{m-1}(j+1)t\\
= &\ \frac{nm(m+1)}{2}-\sum_{j=0}^{m-1}j\lfloor\frac{cj+c-b-1}{a}\rfloor-\sum_{j=0}^{m-1}\lfloor\frac{cj+c-b-1}{a}\rfloor\\
= &\ \frac{nm(m+1)}2-h(c,c-b-1,a,m-1)-f(c,c-b-1,a,m-1)
\end{aligned}
\]
所以可以得到:
\[g(a,b,c,n)=nm(m+1)-2h(c,c-b-1,a,m-1)-2f(c,c-b-1,a,m-1)-f(a,b,c,n)
\]
总结下来就是这样:
\[g(a,b,c,n)=\left\{
\begin{array}{lr}
(n+1)\lfloor\frac b c\rfloor^2 & a=0\\
\\
g(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+
2h(a\bmod c,b\bmod c,c,n)\lfloor\frac{a}{c}\rfloor+\\n(n+1)\lfloor\frac{a}{c}\rfloor\lfloor\frac b c\rfloor+2f(a\bmod c,b\bmod c,c,n)\lfloor\frac b c\rfloor
& a\ge c,b\ge c\\
\\
nm(m+1)-2h(c,c-b-1,a,m-1)-\\2f(c,c-b-1,a,m-1)-f(a,b,c,n) & \text{otherwise}
\end{array}
\right.
\]
\(h\) 的推导
当 \(a=0\) 时,\(h(a,b,c,n)=\frac{n(n+1)}{2}\lfloor\frac b c\rfloor\)。
当 \(a\ge c,b\ge c\) 时:
\[h(a,b,c,n)=h(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
\]
\(h\) 取模的推导过程
然后令 \(m=\lfloor\frac{an+b}c\rfloor,t=\lfloor\frac{cj+c-b-1}a\rfloor\),继续推柿子:
\[\begin{aligned}
h(a,b,c,n) = &\ \sum_{i=0}^ni\lfloor\frac{ai+b}{c}\rfloor\\
= &\ \sum_{i=0}^n\sum_{j=0}^{\lfloor\frac{ai+b}c\rfloor-1}i\\
= &\ \sum_{j=0}^{m-1}\sum_{i=0}^ni[j<\lfloor\frac{ai+b}{c}\rfloor]\\
= &\ \sum_{j=0}^{m-1}\sum_{i=0}^ni[i>t]\\
= &\ \sum_{j=0}^{m-1}\frac{(n-t)(n+t+1)}{2}\\
= &\ \frac 1 2\sum_{j=0}^{m-1}(n^2+n-t^2-t)\\
= &\ \frac{mn(n+1)}{2}-\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{mn(n+1)}{2}-g(c,c-b-1,a,m-1)-f(c,c-b-1,a,m-1)
\end{aligned}
\]
总结下来就是这样:
\[h(a,b,c,n)=\left\{
\begin{array}{lr}
\frac{n(n+1)}{2}\lfloor\frac b c\rfloor & a=0\\
h(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{mn(n+1)}{2}-g(c,c-b-1,a,m-1)-f(c,c-b-1,a,m-1) & \text{otherwise}
\end{array}
\right.
\]
Ex-extend
上面这三个柿子都是基于 \(a,b,c\) 均为非负整数的基础上的(否则不等式的推导有问题)。那么当 \(a,b,c\) 小于 \(0\) 时该怎么办?
- \(a<0\):\(k=\lceil\frac{-a}{c}\rceil, \lfloor\frac{ai+b}{c}\rfloor\rightarrow\lfloor\frac{(ck+a)i+b}{c}\rfloor-ki\);
- \(b<0\):\(k=\lceil\frac{-b}{c}\rceil,\lfloor\frac{ai+b}c\rfloor\rightarrow\lfloor\frac{ai+(ck+b)}{c}\rfloor-k\)
- \(c<0\):不知道有没有更简单的做法,先放一个自己口胡的(
注意到有 \(\lfloor\frac{ai+b}{c}\rfloor=-\lceil\frac{ai+b}{-c}\rceil\),所以原式可以化一下:
\[\begin{aligned}
f(a,b,c,n) = &\ -\sum_{i=0}^n\lceil\frac{ai+b}{-c}\rceil\\
= &\ -\left(\sum_{i=0}^n\lfloor\frac{ai+b}{-c}\rfloor+n+1-\sum_{i=0}^n[-c\mid(ai+b)]\right)\\
\end{aligned}
\]
其中 \(\sum_{i=0}^n[-c\mid(ai+b)]\) 是可以在 \(\log\) 的时间内求出来的,于是原式就出来了(
恶心-extend
LibreOJ #138
给定 \(n,a,b,c,k_1,k_2\),求:
\[\sum_{x=0}^nx^{k_1}\left\lfloor\frac{ax+b}c\right\rfloor^{k_2}\bmod p
\]
\(T=1000\),\(1\le n,a,c\le10^9\),\(0\le b\le 10^9\),\(0\le k_1+k_2\le10\),\(p=10^9+7\)。
![](https://cdn.luogu.com.cn/upload/image_hosting/es9szz0w.png)
待填坑
Problems
- P5170 【模板】类欧几里得算法
求 \(\sum_{i=0}^n\lfloor\frac{ai+b}c\rfloor\),\(\sum_{i=0}^n\lfloor\frac{ai+b}c\rfloor^2\),\(\sum_{i=0}^ni\lfloor\frac{ai+b}c\rfloor\),对 \(998244353\) 取模。
这题显然就是刚才的 \(f,g,h\) 的计算。注意到 \(g,h\) 的计算中有很多的重复调用,因此我们可以将这三个函数同步计算。复杂度 \(O(\log(a+c))\)。
- P5171 Earthquake
求 \(ax+by\le c\) 的非负整数解个数。
把原式变换一下:
\[ax+by\le c\\
by\le c-ax\\
y\le\lfloor\frac{c-ax}{b}\rfloor
\]
所以对于每个 \(x\) 的可能取值,\(y\) 都有 \(\lfloor\frac{c-ax}{b}\rfloor+1\) 种取值(加 \(1\) 是因为 \(y\) 可以取 \(0\))。又注意到当 \(x>\lfloor\frac c a\rfloor\) 时 \(c-ax<0\),所以解数的式子就出来了:
\[\sum_{x=0}^{\lfloor\frac c a\rfloor}(\lfloor\frac{c-ax}{b}\rfloor+1)
\]
稍微推导一下:
\[\begin{aligned}
\sum_{x=0}^{\lfloor\frac c a\rfloor}(\lfloor\frac{c-ax}{b}\rfloor+1) = &\ \sum_{x=0}^{\lfloor\frac c a\rfloor}\lfloor\frac{c-ax}{b}\rfloor+\lfloor\frac{c}{a}\rfloor+1\\
= &\ \sum_{x=0}^{\lfloor\frac c a\rfloor}(\lfloor\frac{(b-a)x+c}{b}\rfloor-x)+\lfloor\frac{c}{a}\rfloor+1\\
= &\ \sum_{x=0}^{\lfloor\frac c a\rfloor}\lfloor\frac{(b-a)x+c}{b}\rfloor-\frac{\lfloor\frac{c}{a}\rfloor(\lfloor\frac{c}{a}\rfloor+1)}{2}+\lfloor\frac{c}{a}\rfloor+1\\
\end{aligned}
\]
前面显然可以用前面 \(f\) 函数来解决,如果 \(a>b\) 那么 \(\operatorname{swap}(a,b)\) 即可。
- P5172 Sum
求 \(\sum_{d=1}^n(-1)^{\lfloor d\sqrt r\rfloor}\)。
首先注意到一个性质:
\[\begin{aligned}
(-1)^x = &\
\begin{cases}
1 & x\equiv0\pmod2\\
-1 & x\equiv1\pmod2\\
\end{cases}\\
= &\ 1-2x+4\lfloor\frac x 2\rfloor
\end{aligned}
\]
所以原式可以化为:
\[\begin{aligned}
\sum_{d=1}^n(-1)^{\lfloor d\sqrt r\rfloor} = &\ \sum_{d=1}^n(1-2\lfloor d\sqrt r\rfloor+4\lfloor\frac { d\sqrt r} 2\rfloor)\\
= &\ n-2\sum_{d=1}^n\lfloor d\sqrt r\rfloor+4\sum_{d=1}^n\lfloor\frac { d\sqrt r} 2\rfloor
\end{aligned}
\]
设 \(f(a,b,c,n)=\sum_{d=1}^n\lfloor\frac{a\sqrt r+b}{c}d\rfloor\),那么原式可以化为 \(n-2f(1,0,1,n)+4f(1,0,2,n)\)。
令 \(x=\sqrt r\),\(k=\frac{ax+b}{c}\),那么 \(f(a,b,c,n)=\sum_{d=1}^n\lfloor kd\rfloor\)。
然后利用类欧的思想推个柿子:
- \(k\ge 1,\lfloor k\rfloor\not=0\):
\[\begin{aligned}
\sum_{d=1}^n\lfloor kd\rfloor = &\ \sum_{d=1}^n\lfloor kd-\lfloor k \rfloor d+\lfloor k \rfloor d\rfloor\\
= &\ \sum_{d=1}^n\lfloor (\frac{ax+b}{c}-\lfloor k \rfloor )d\rfloor+\frac{n(n+1)}{2}\lfloor k \rfloor \\
= &\ \sum_{d=1}^n\lfloor \frac{ax+b-c\lfloor k \rfloor}{c}d\rfloor+\frac{n(n+1)}{2}\lfloor k \rfloor \\
= &\ f(a,b-c\lfloor k \rfloor,c,n)+\frac{n(n+1)}{2}\lfloor k \rfloor
\end{aligned}
\]
- \(k<1,\lfloor k\rfloor=0\):
\[\begin{aligned}
\sum_{d=1}^n\lfloor kd\rfloor = &\ \sum_{d=1}^n\sum_{i=1}^{\lfloor kn\rfloor}[i< kd]\\
= &\ \sum_{i=1}^{\lfloor kn\rfloor}\sum_{d=1}^n[d>\lfloor\frac i k\rfloor]\\
= &\ \sum_{i=1}^{\lfloor kn\rfloor}(n-\lfloor\frac i k\rfloor)\\
= &\ n\cdot\lfloor kn\rfloor-\sum_{i=1}^{\lfloor kn\rfloor}\lfloor\frac c {ax+b}i\rfloor\\
= &\ n\cdot\lfloor kn\rfloor-\sum_{i=1}^{\lfloor kn\rfloor}\lfloor\frac {c(ax-b)} {(ax+b)(ax-b)}i\rfloor\\
= &\ n\cdot\lfloor kn\rfloor-\sum_{i=1}^{\lfloor kn\rfloor}\lfloor\frac {acx-bc} {a^2r-b^2}i\rfloor\\
= &\ n\cdot\lfloor kn\rfloor-f(ac,-bc,a^2r-b^2,\lfloor kn\rfloor)
\end{aligned}
\]
由于 \(x\) 是无理数,最后一步要做一遍有理化。分子分母在计算过程中要约分,否则会炸掉。
- P5179 Fraction
求一个分子分母最小的最简分数 \(\frac p q\),满足 \(\frac a b<\frac pq<\frac cd\)。
分类讨论一下。
- \(\lfloor\frac ab\rfloor+1\le\lceil\frac cd\rceil-1\):此时 \(\frac ab\) 和 \(\frac cd\) 中间有一个整数,取 \(p=\lfloor\frac ab\rfloor+1\),\(q=1\) 即可。
- \(a=0\):此时 \(\frac ab=0\),那么只需满足 \(\frac cd\) 的条件,取 \(p=1\),\(q=\lfloor\frac dc\rfloor+1\) 即可。
- \(a<b\):可以同时取倒数处理,递归求解 \(\frac dc<\frac qp<\frac ba\) 即可。
- \(a\ge b\):令 \(k=\lfloor\frac ab\rfloor\),那么可以把原式全都减去 \(k\),递归求解 \(\frac {a-kb}b<\frac{p-kq}q<\frac{c-kd}d\) 即可。
注意到前两种情况其实都是边界条件,而后两种情况其实就是一种辗转相除法,故也属于类欧几里得算法。
- P4433 [COCI2009-2010#1] ALADIN
解决题目的关键显然在于维护 \(\sum_{i=1}^ni\times A\bmod B\) 这个式子。
稍微转化一下:
\[\begin{aligned}
\sum_{i=1}^ni\times A\bmod B = &\ \sum_{i=1}^n\left(i\times A-\lfloor\frac{i\times A}B\rfloor B\right)\\
= &\ A\sum_{i=1}^ni-B\sum_{i=1}^n\lfloor\frac{i\times A}B\rfloor\\
= &\ \frac{n(n+1)}2A-B\cdot f(A,0,B,n)
\end{aligned}
\]
于是可以 \(\log\) 的时间内求出值。然后把每个操作的 \(l,r\) 离散化一下,线段树维护即可。
Epilogue
水。
能水五道黑题。
发财。