【题目链接】
【前置技能】
- 逆元
【题解】
- 题目要求的是最小的非负整数 t t t,使得 x + t ∗ m ≡ y + t ∗ n ( m o d L ) x+t*m\equiv y+t*n~(mod~L) x+t∗m≡y+t∗n (mod L),移项,合并同类项,得到 t ∗ ( n − m ) ≡ x − y ( m o d L ) t*(n-m)\equiv x-y~(mod~L) t∗(n−m)≡x−y (mod L),这里不妨设 n ≥ m n\geq m n≥m。
- 发现这其实就是一个线性同余方程。令 d = g c d ( n − m , L ) d = gcd(n-m,L) d=gcd(n−m,L),那么有解的条件是 d ∣ ( x − y ) d~|~(x-y) d ∣ (x−y)。解得 t ≡ ( ( n − m ) / d ) − 1 ∗ ( x − y ) / d ( m o d ( L / d ) ) t\equiv ((n-m)/d)^{-1}*(x-y)/d~(mod~(L/d)) t≡((n−m)/d)−1∗(x−y)/d (mod (L/d)),输出一个最小非负整数解即可。
- 时间复杂度 O ( l o g N ) O(logN) O(logN)
【代码】
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
LL x, y, m, n, l, a, b;
template <typename T> void chkmin(T &x, T y){x = min(x, y);}
template <typename T> void chkmax(T &x, T y){x = max(x, y);}
template <typename T> void read(T &x){
x = 0; int f = 1; char ch = getchar();
while (!isdigit(ch)) {if (ch == '-') f = -1; ch = getchar();}
while (isdigit(ch)) {x = x * 10 + ch - '0'; ch = getchar();}
x *= f;
}
LL gcd(LL a, LL b){
if (a == 0 || b == 0) return a + b;
return gcd(b, a % b);
}
void exgcd(LL a, LL b, LL &x, LL &y){
if (b == 0) {x = 1, y = 0; return;}
LL q = a / b, r = a % b;
exgcd(b, r, y, x);
y -= x * q;
}
int main(){
read(x), read(y), read(m), read(n), read(l);
if (n < m) {swap(n, m); swap(x, y);}
LL d = gcd(l, n - m);
if ((x - y) % d) printf("Impossible\n");
else {
LL a = n - m, b = x - y;
a /= d, b /= d, l /= d;
exgcd(a, l, x, y);
LL ans = (b % l) * (x % l) % l;
if (ans < 0) ans += l;
printf("%lld\n", ans);
}
return 0;
}