题目链接:https://www.acwing.com/problem/content/224/
解题思路:
对于这道题目,首先可以列出这个等式:y + n k = x + mk + Lu;
然后进行移项得到:(n - m)k - uL = x - y;
注意这里的符号,不管符号是正还是符号都可以直接套用exgcd;
需要注意的是:只有当(x - y) % (n - m, L) == 0的时候,这个方程才有解集。
对于这道题目,我们通过exgc得到k之后,我们还需要让k *= (x - y) / d;因为exgcd得到的X0针对的情况是等式的左边刚好是(a, b)的时候,所以我们需要乘上一个数;
然后这道题目要求最少的步数,其实对于方程来说就是求最小的正的x;而所有的解集:x = X0 + h(b / d);
需要注意这里的b / d可能是一个负数,但是我们在求其解集的时候是正数还是负数是没有任何影响的,因为h可以取任意的整数,由于这道题目想要求得是最小的而且是正数,所以我们需要取得b / d的绝对值,然后让 x = (x % tmp + tmp) % tmp;即可。
代码一份:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;
LL xx, yy, m, n, l;
inline LL gcd(LL x, LL y) {
return y == 0 ? x : gcd(y, x % y);
}
inline 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 = y - a / b * x;
return d;
}
int main(void) {
// freopen("in.txt", "r", stdin);
scanf("%lld%lld%lld%lld%lld", &xx, &yy, &m, &n, &l);
if((yy - xx) % gcd(m - n, l)) puts("Impossible");
else {
LL x, y;
LL d = exgcd(m - n, l, x, y);
x *= (yy - xx) / d;
LL tmp = abs(l / d);
x = (x % tmp + tmp) % tmp;
printf("%lld\n", x);
}
return 0;
}