考爆了,爆零,GG.
T1:方程的解
一眼Exgcd,求出最小解,再求出所有解。
然而Exgcd忘了,面向数据范围编程,特判少了,40分滚粗。
这题要特判的太多了。。。
- 要注意特判0
- 要注意特判符号
- 要注意特判有无正整数解
大体来说就是这3条,关于符号的问题,Exgcd肯定要正数,可以先把负数标记一下,取相反数,Exgcd后再改回来。
关于Exgcd,有必要再证明一下。。。
已知不定方程\(ax + by = c\),首先由某不记得名字的推论,它有解的必要条件为 \((a, b) | c\).
我们设\(g = (a, b)\),先求解\(ax + by = g\).
因为\((a, b) = (b, a % b), a % b = a - b * \lfloor \frac{a}{b} \rfloor\),所以\(bx + (a - b * \lfloor \frac{a}{b} \rfloor)y = g\).即:\(ay + b(x - \lfloor \frac{a}{b} \rfloor y) = g\).
可得原方程一组解 \(x_1 = y, y_1 = x - \lfloor \frac{a}{b} \rfloor y\).
而\(c = kg\),我们令该不定方程两边同乘\(k\)得 \(ax_0 + by_0 = c\), 其中\(x_0 = kx_1, y_0 = ky_1\).
这是原方程的一组特解。要获得同解,我们让\(x + \Delta x, y + \Delta y\). \(a(x_0 + \Delta x) + b (y_0 + \Delta y) = c\).为使方程平衡,\(a \Delta x = b \Delta y\).
所以\(\Delta x = \frac{b}{g}, \Delta y = \frac{a}{g}\).
原方程同解为$x = x_0 + t \frac{b}{g}, y = y_0 - t \frac{a}{g}, t \in Z $.
求出刚好大于0的y,求出刚好大于0的x对应的最大y,差值除以步长\(\frac{a}{g}\)再+1就是答案。
本题过于难调,\(Have\ fun\ debugging!\) (逃
#include <bits/stdc++.h>
#define ll long long
ll Exgcd(ll a, ll b, ll &x, ll &y) {
if (b == 0) {
x = 1, y = 0; return a;
}
ll r = Exgcd(b, a % b, y, x);
y -= (a / b) * x;
return r;
}
ll Solve(ll a, ll b, ll c) {
bool opa = 0, opb = 0;
if (a == 0 && b == 0) return c == 0 ? -1 : 0;
if (a == 0) return (c == 0 || (c % b == 0 && c / b > 0)) ? -1 : 0;
if (b == 0) return (c == 0 || (c % a == 0 && c / a > 0)) ? -1 : 0;
if (c < 0) a = -a, b = - b, c = -c;
if (a < 0) a = -a, opa = 1;
if (b < 0) b = -b, opb = 1;
ll x, y;
ll g = Exgcd(a, b, x, y);
if (c % g != 0) return 0;
ll t = c / g; x *= t, y *= t, a /= g, b /= g, c = t;
if (opa) a = -a, x = -x;
if (opb) b = -b, y = -y;
if (a < 0) a = -a, b = -b, c = -c;
if (a * b < 0) return -1;
x %= b;
while (x <= 0) x += b;
y = (c - a * x) / b;
if (y < 0) return 0;
ll y_min = y % a;
while (y_min <= 0) y_min += a;
return y_min <= y ? (y - y_min) / a + 1 : 0;
}
signed main() {
int T;
scanf("%d", &T);
while (T--) {
ll a, b, c;
scanf("%lld%lld%lld", &a, &b, &c);
ll ans = Solve(a, b, c);
if (ans == -1 || ans > 65535) puts("ZenMeZheMeDuo");
else printf("%lld\n", ans);
}
}