You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

84 lines
3.4 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
//扩展欧几里得
LL exgcd(LL a, LL b, LL &x, LL &y) {
if (!b) {
x = 1, y = 0;
return a;
}
LL d = exgcd(b, a % b, y, x);
y -= a / b * x;
return d;
}
/*
测试用例:
1
2 3 5
答案:
1 1 1 1 1
*/
int main() {
int t;
scanf("%d", &t);
while (t--) {
LL a, b, c;
scanf("%lld %lld %lld", &a, &b, &c);
LL x, y;
LL d = __gcd(a, b); //使用库函数__gcd计算最大公约数d
if (c % d) //裴蜀定理,当gcd(a,b)不能整除c时方程无解,输出-1
puts("-1");
else {
//这步很值得总结一个方程拿到手第一步是化简就是把a,b,c中都除以gcd(a,b),实现化简
//举个栗子2x+4y=8 -> x+2y=4 很直白吧,套路吧~ 此方程与原方程的角系一样吧~
//当然,也可能化简不了,比如: 2x+3y=5,因为gcd(2,3)=1,化不化简都一样
//但这里有一个事实,因为 a'=a/gcd(a,b),b'=b/gcd(a,b)后a',b'肯定是互质。
//令d'=gcd(a',b') 现在d'=1
a /= d, b /= d, c /= d;
//扩展欧几里得一通用形式返回d,在有的题解中不采用exgcd返回d,而是用__gcd计算d.
//把扩展欧几里得算法定位为取特解x,y专用也是比较直观简便的。
//性能上嘛,由于辗转相除法不断的变更除数,速度上很快,两次也没有问题。
//扩欧的形式ax+by=gcd(a,b),求方程的一组解 x,y。现在的情况下gcd(a,b)=1了可以
exgcd(a, b, x, y);
x *= c, y *= c; //结果(x,y)需要乘以c才能还原为ax+by=c的方程解。
/*
通解公式: x=x0+b/d*t
y=y0-a/d*t
此时d=1,则通解公式:
x=x0+b*t
y=y0-a*t
想要xmin => x0固定值b固定值只能变化的是t,每变化一次就增加、减少一个b
*/
// printf("x=%lld y=%lld a=%lld b=%lld\n", x, y, a, b);
LL xmin = (x % b + b) % b; //利用最小正整数解的公式(需要特判0)
if (xmin == 0) xmin = b; // xmin如果是0需要特判,加一个b搞定~
LL ymin = (y % a + a) % a; //利用最小正整数解的公式(需要特判0)
if (ymin == 0) ymin = a; // ymin如果是0需要特判,加一个a搞定~
// printf("xmin=%lld ymin=%lld\n", xmin, ymin);
// x最大值怎么求呢简单利用原始方程变形求
// ax+by=c => ax=c-by => x = (c-by)/a
// x要想最大则y必须取最小值
LL xmax = (c - b * ymin) / a;
// y要想最大则x必须取最小值
LL ymax = (c - a * xmin) / b;
if (xmax <= 0 || ymax <= 0) //若最大值还不是正整数,则无正整数解
printf("%lld %lld\n", xmin, ymin); //输出最小值
else {
//解的个数是最大 x 最小 x 的差除以模数 b 再加上1。
LL sum = (xmax - xmin) / b + 1; //不足b时也有1个解+b就增加一个解
printf("%lld %lld %lld %lld %lld\n", sum, xmin, ymin, xmax, ymax);
}
}
}
return 0;
}