题解: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;
}
posted @ 2020-10-22 12:04  JiaZP  阅读(122)  评论(0编辑  收藏  举报