类欧几里得算法
类欧几里得算法主要利用了分数的递归结构,不断进行迭代,而由于这和欧几里得算法有直接联系而得名。
给定 \(a, b, c, d\),求字典序最小的 \((q, p)\) 满足:
\[\dfrac{a}{b} < \dfrac{q}{p} < \dfrac{c}{d}
\]
首先若
\[\lfloor\dfrac{a}{b}\rfloor + 1 < \dfrac{c}{d}
\]
那么直接取 \((q, p) = (1, \lfloor\dfrac{a}{b}\rfloor + 1)\) 即可,显然最小。
否则,显然有
\[\lfloor\dfrac{a}{b}\rfloor \le \dfrac{a}{b} < \dfrac{q}{p} < \dfrac{c}{d} \le \lfloor\dfrac{a}{b}\rfloor + 1
\]
于是 \(\dfrac{q}{p}\) 的整数部分为 \(\lfloor\dfrac{a}{b}\rfloor\),然后全部减去 \(\lfloor\dfrac{a}{b}\rfloor\) 再取倒数,即求出
\[\dfrac{d}{c - d\lfloor\dfrac{a}{b}\rfloor}< \dfrac{q}{p-q\lfloor\dfrac{a}{b}\rfloor} < \dfrac{b}{a-b\lfloor\dfrac{a}{b}\rfloor}
\]
\[\dfrac{d}{c - d\lfloor\dfrac{a}{b}\rfloor}< \dfrac{q}{p-q\lfloor\dfrac{a}{b}\rfloor} < \dfrac{b}{a \bmod b}
\]
但是现在有一个问题:这样迭代求得的是 \((p, q)\) 字典序最小的解,但是我们要求的是 \((q, p)\) 字典序最小的解,事实上这两个解一定是同一个,如果不同,假设 \(p/q\) 是 \((q, p)\) 字典序最小的一组解,\(r/s\) 是字典序 \((r, s)\) 最小的一组解,\(r/s \neq p/q\),那么显然 \(r < p, q < s\),即
\[\dfrac{a}{b} < \dfrac{r}{s} < \dfrac{r}{q} < \dfrac{p}{q} < \dfrac{c}{d}
\]
所以 \(\dfrac{r}{q}\) 满足条件且无论以哪种字典序都更优。
时间复杂度 \(\mathcal{O}(\log\min(p, q))\)。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
// typedef __int128 i128;
typedef pair<int, int> pii;
const int N = 2e5 + 10, mod = 998244353;
template<typename T>
void dbg(const T &t) { cout << t << endl; }
template<typename Type, typename... Types>
void dbg(const Type& arg, const Types&... args) {
cout << arg << ' ';
dbg(args...);
}
namespace Loop1st {
void solve(int a, int b, int &p, int &q, int c, int d) {
if ((a / b + 1) * d < c) {
p = a / b + 1;
q = 1;
return ;
}
solve(d, c - d * (a / b), q, p, b, a % b);
p += q * (a / b);
} // 因为 a, b, c, d < 10 ^ 9, a / b < c / d 所以 int 足够了
void main() {
int a, b, c, d, p, q;
while (cin >> a >> b >> c >> d) {
solve(a, b, p, q, c, d);
cout << p << '/' << q << '\n';
}
}
}
int main() {
// freopen("data.in", "r", stdin);
// freopen("data.out", "w", stdout);
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int T = 1;
// cin >> T;
while (T--) Loop1st::main();
return 0;
}
Floor_Sum 问题
求 \(f(a, b, c, n) = \sum\limits_{i=0}^n\left\lfloor\dfrac{ai+b}{c}\right\rfloor\)。
其中 \(a, b, c, n \in \mathbb{N}^*\)。
代数推导
首先将问题转化为 \(a < c, b < c\) 的情形:
\[f(a, b, c, n) = \sum\limits_{i=0}^n\left\lfloor\dfrac{ai+b}{c}\right\rfloor
\]
\[=\sum\limits_{i=0}^n\left\lfloor \dfrac{(\lfloor\dfrac{a}{c}\rfloor c+(a\bmod c))i + (\lfloor\dfrac{b}{c}\rfloor c+(b\bmod c))}{c}\right\rfloor
\]
\[=\sum\limits_{i=0}^n\left\lfloor\dfrac{a}{c}\right\rfloor i+\left\lfloor\dfrac{b}{c}\right\rfloor + \left\lfloor \dfrac{(a\bmod c)i + (b\bmod c)}{c}\right\rfloor
\]
\[=\dfrac{n(n+1)}{2}\left\lfloor\dfrac{a}{c}\right\rfloor+
(n+1)\left\lfloor\dfrac{b}{c}\right\rfloor+
f(a\bmod c, b\bmod c, c, n)\]
然后考虑 \(a < c, b < c\) 的情况:
令 \(m = \left\lfloor\dfrac{an+b}{c}\right\rfloor\)
那么
\[f(a, b, c, n) = \sum\limits_{i=0}^n\sum\limits_{j=0}^{m-1}{\left[j < \left\lfloor\dfrac{ai+b}{c}\right\rfloor\right]}
\]
我们有
\[\left\lfloor\dfrac{ai+b}{c}\right\rfloor = \left\lceil\dfrac{ai+b+1}{c}\right\rceil-1
\]
于是转化为
\[f(a, b, c, n) = \sum\limits_{i=0}^n\sum\limits_{j=0}^{m-1}{\left[j + 1 < \left\lceil\dfrac{ai+b+1}{c}\right\rceil\right]}
\]
\[= \sum\limits_{i=0}^n\sum\limits_{j=0}^{m-1}{\left[j + 1 < \dfrac{ai+b+1}{c}\right]}
\]
\[= \sum\limits_{i=0}^n\sum\limits_{j=0}^{m-1}{\left[\left\lfloor\dfrac{cj+c-b-1}{a}\right\rfloor < i\right]}
\]
\[= \sum\limits_{j=0}^{m-1}\sum\limits_{i=0}^n{\left[\left\lfloor\dfrac{cj+c-b-1}{a}\right\rfloor < i\right]}
\]
\[= \sum\limits_{j=0}^{m-1}\left(n-\left\lfloor\dfrac{cj+c-b-1}{a}\right\rfloor\right)
\]
\[= nm-f(c, c - b - 1, a, m - 1)
\]
此时 \(a'=c, c'=a, a'>c'\) 又变成了上面的情况。
时间复杂度 \(\mathcal{O}(\log\min(a, c))\),类似欧几里得算法的证明。
同时,若 \(m = 0\),立即终止的话,复杂度会变为 \(\mathcal{O}(\log\min(a, c, n))\),证明参见 OIWiki。
几何直观
相当于直线 \(y = \dfrac{ax+b}{c}\) 在 \([0, n]\) 上的整点个数。推导过程可以看 OIWiki。
例题
转化一下:
\[(Ak+B)\bmod M > k
\]
\[(Ak+B)\bmod M \ge k + 1
\]
\[(Ak+B)-M\left\lfloor\dfrac{Ak+B}{M}\right\rfloor\ge k+1
\]
\[\left\lfloor\dfrac{Ak+B}{M}\right\rfloor \le \left\lfloor\dfrac{(A-1)k+B-1}{M}\right\rfloor
\]
由于
\[\left\lfloor\dfrac{Ak+B}{M}\right\rfloor - \left\lfloor\dfrac{(A-1)k+B-1}{M}\right\rfloor \in [0, 1] \cap\mathbb N
\]
所以答案就是
\[N - \left(\sum\limits_{k=0}^{N-1}\left\lfloor\dfrac{Ak+B}{M}\right\rfloor - \left\lfloor\dfrac{(A-1)k+B-1}{M}\right\rfloor\right)
\]
为了防止 \(B = 0\) 的特判,考虑把 \(N\) 加在里面,变成
\[\sum\limits_{k=0}^{N-1}\left(\left\lfloor\dfrac{(A-1)k+B-1+M}{M}\right\rfloor-\left\lfloor\dfrac{Ak+B}{M}\right\rfloor\right)
\]
套一个类欧板子即可,时间复杂度 \(\mathcal{O}(T\log\min(N, M, A))\),代码中变量名有所不同。
求
\[f(a, b, c, n) = \sum\limits_{i=0}^n\left\lfloor\dfrac{ai+b}{c}\right\rfloor, g(a, b, c, n) = \sum\limits_{i=0}^ni\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
\]
类似 \(f\) 的推导,我们有:
\[g(a, b, c, n) = g(a \bmod c, b \bmod c, 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}
\]
\[h(a, b, c, n) = h(a \bmod c, b \bmod c, 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)+
\left\lfloor\dfrac{a}{c}\right\rfloor \left\lfloor\dfrac{b}{c}\right\rfloor n(n+1)+2\left\lfloor\dfrac{b}{c}\right\rfloor f(a\bmod c, b\bmod c, c, n) + 2\left\lfloor\dfrac{a}{c}\right\rfloor g(a\bmod c, b\bmod c, c, n) \]
考虑 \(a < c, b < c\) 的情况:
对于和式
\[\sum\limits_{i=0}^n i^r\left\lfloor\dfrac{ai+b}{c}\right\rfloor^s
\]
我们只需将求解 \(f\) 的过程中
\[\sum\limits_{i=0}^n\sum\limits_{j=0}^{m-1}{\left[j < \left\lfloor\dfrac{ai+b}{c}\right\rfloor\right]}
\]
这步,改为
\[\sum\limits_{i=0}^n\sum\limits_{j=0}^{m-1}{i^r((j+1)^s-j^s)\left[j < \left\lfloor\dfrac{ai+b}{c}\right\rfloor\right]}
\]
即可,之后类似推导。
对于 \(g\):
\[g(a, b, c, n)=\sum\limits_{i=0}^n\sum\limits_{j=0}^{m-1}{i\left[j < \left\lfloor\dfrac{ai+b}{c}\right\rfloor\right]}
\]
\[= \sum\limits_{j=0}^{m-1}\sum\limits_{i=0}^ni{\left[\left\lfloor\dfrac{cj+c-b-1}{a}\right\rfloor < i\right]}
\]
\[= \sum\limits_{j=0}^{m-1}\sum\limits_{i=0}^n\dfrac{1}{2}\left(n+\left\lfloor\dfrac{cj+c-b-1}{a}\right\rfloor+1\right)\left(n-\left\lfloor\dfrac{cj+c-b-1}{a}\right\rfloor\right)
\]
\[=\dfrac{1}{2}mn(n+1)-\dfrac{1}{2}f(c, c - b - 1, a, m - 1) - \dfrac{1}{2}h(c, c - b - 1, a, m - 1)
\]
对于 \(h\):
\[h(a, b, c, n)=\sum\limits_{i=0}^n\sum\limits_{j=0}^{m-1}{(2j+1)\left[j < \left\lfloor\dfrac{ai+b}{c}\right\rfloor\right]}
\]
\[= \sum\limits_{j=0}^{m-1}(2j+1)(n-\left\lfloor\dfrac{cj+c-b-1}{a}\right\rfloor)
\]
\[=nm^2-f(c, c - b - 1, a, m - 1) - 2g(c, c - b - 1, a, m - 1)
\]
递归计算 \(f, g, h\) 即可,时间复杂度 \(\mathcal{O}(\log\min(a, c, n))\)。