扩展欧几里得算法:对方程 ax + by = gcd(a, b) ,该算法可以找出这个方程的一对整数解 (x, y) ,这里的 x 和 y 不一定是正数,也可能是负数或零。算法代码如下:
1 //d就是gcd(a,b), (x,y)就是式子 ax+by=gcd(a,b) 的一个解 2 void exgcd(int a, int b, int& d, int& x, int& y){ 3 if(!b) { d = a; x = 1; y = 0; } 4 else { exgcd(b, a%b, d, y, x); y -= x*(a/b); } 5 }
上面的代码仅仅是可以求出方程的一组解,我们还得求出其他解,我们可以经过推导可以得出这个方程的通解为 (x+kn, y-km) ,这里的k为任意整数,n=b/gcd(a,b),m=a/gcd(a,b) 。这就是我们这个方程的通解的表达式。
由以上结论,我们可以推导下一个结论:一个方程 ax + by = c 中,令 g=gcd(a,b), 若 c 是 g 的倍数,则该方程的一组解就是 (x*c/g, y*c/g),若 c 不是 g 的倍数,则该方程无整数解。
有了以上结论,我们就可以试试下面这题了:
https://vjudge.net/problem/OpenJ_Bailian-1061
我们假设青蛙跳了 t 次才能碰面,则我们可以列出式子:(x+m*t)%L = (y+n*t)%L , 我们将其变型一下:x-y = t*(n-m) + k*L ,我们可以通过扩欧算法求出 t 和 k 的一个整数解。具体代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 5 void exgcd(LL a, LL b, LL& d, LL& x, LL& y){ 6 if(!b) { d = a; x = 1; y = 0; } 7 else { exgcd(b, a%b, d, y, x); y -= x*(a/b); } 8 } 9 10 int main(){ 11 LL a, b, d, x, y, t, m, n, L; 12 cin >> a >> b >> m >> n >> L; 13 t = a - b; 14 exgcd(n-m, L, d, x, y); 15 if(t%d != 0) { 16 cout << "Impossible" << endl; 17 }else { 18 x = t / d * x; 19 x = (x % L + L) % L; 20 cout << x << endl; 21 } 22 return 0; 23 }