题解:P5171 Earthquake
不会类欧的可以看这里
枚举 \(x\),那么合法的 \(y\) 的个数为 \(\lfloor \dfrac{c - ax}{b} \rfloor+1\)。那么题目要求的就是:
\[\sum_{x=0}^{\lfloor \frac{c}{a} \rfloor} \lfloor \frac{c-ax}b \rfloor+1
\]
发现和类欧的唯一区别是 \(x\) 的系数是负数。但是我们可以在分子上加一个 \(bx\) 即可。这里假设 \(b \ge a\),当 \(b < a\) 的时候可以交换 \(a,b\)。
\[\begin{aligned}
\sum_{x=0}^{\lfloor \frac{c}{a} \rfloor} \lfloor \frac{(b-a)x+c}{b} \rfloor - x + 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}
\]
然后直接用类欧算即可。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
typedef long long ll;
template <typename T> inline void read(T &x) {
x = 0; char c = getchar(); bool flag = false;
while (!isdigit(c)) { if (c == '-') flag = true; c = getchar(); }
while (isdigit(c)) { x = (x << 1) + (x << 3) + (c ^ 48); c = getchar(); }
if (flag) x = -x;
}
using namespace std;
inline ll sol(ll a, ll b, ll c, ll n) {
if (!a) return (n + 1) * (b / c);
if (a >= c || b >= c) {
return n * (n + 1) / 2 * (a / c) + (n + 1) * (b / c) + sol(a % c, b % c, c, n);
}
ll m = (a * n + b) / c;
return n * m - sol(c, c - b - 1, a, m - 1);
}
int main() {
ll a, b, c; read(a), read(b), read(c);
if (b < a) swap(b, a);
ll res = 0;
res += sol(b - a, c, b, c / a);
res -= (c / a) * (c / a + 1) / 2;
res += c / a;
++res;
cout << res << endl;
return 0;
}