扩展欧几里得

扩展欧几里得算法:对方程 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 的一个整数解。具体代码如下:

 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 }
View Code
原文地址:https://www.cnblogs.com/DynastySun/p/9364142.html