題解:P5171 Earthquake
阿新 • • 發佈:2020-10-22
不會類歐的可以看這裡
列舉 \(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; }