最近想刷一刷数论的题,就先找了道简单的入手。
这一看就是exgcd求不定方程。
首先可以列出来:x + m * k ≡ y + n * k (mod L)
化简:x + m * k - y - n * k = p * L
(m - n) * k - p * L = y - x
令a = m - n, b = L, c = y - x,于是
a * k - b * p = c
首先要保证a,b是正的。
代入exgcd求得ak + bp = 1的解k', p',在gcd(a, b) | c的情况下,得出解k = k' * c / gcd(a, b)。
最小整数解就是(k + m) % m。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<algorithm> 5 #include<cstring> 6 #include<cstdlib> 7 #include<cctype> 8 #include<vector> 9 #include<stack> 10 #include<queue> 11 using namespace std; 12 #define enter puts("") 13 #define space putchar(' ') 14 #define Mem(a, x) memset(a, x, sizeof(a)) 15 #define rg register 16 typedef long long ll; 17 typedef double db; 18 const int INF = 0x3f3f3f3f; 19 const db eps = 1e-8; 20 const int maxn = 105; 21 inline ll read() 22 { 23 ll ans = 0; 24 char ch = getchar(), last = ' '; 25 while(!isdigit(ch)) {last = ch; ch = getchar();} 26 while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();} 27 if(last == '-') ans = -ans; 28 return ans; 29 } 30 inline void write(ll x) 31 { 32 if(x < 0) x = -x, putchar('-'); 33 if(x >= 10) write(x / 10); 34 putchar(x % 10 + '0'); 35 } 36 37 ll n, m, x, y, L; 38 39 ll gcd(ll a, ll b) 40 { 41 return b ? gcd(b, a % b) : a; 42 } 43 void exgcd(ll a, ll b, ll &x, ll &y) 44 { 45 if(!b) x = 1, y = 0; 46 else exgcd(b, a % b, y, x), y -= a / b * x; 47 } 48 49 int main() 50 { 51 x = read(); y = read(); m = read(); n = read(); L = read(); 52 if(m - n < 0) swap(n, m), swap(x, y); 53 ll a = m - n, b = L, c = y - x, k, p; 54 exgcd(a, b, k, p); 55 ll g = gcd(a, b), m = b / g; 56 if(c % g) printf("Impossible\n"); 57 else write((k * (c / g) % m + m) % m); 58 return 0; 59 }