扩展欧几里得算法
扩展欧几里得(改)
对于 a 、b 不全为0,存在整数 x 和 y 使得 gcd(a,b)=x*a+y*b ; 整数。。。也就是可以是负的。
代码:
1 int exGcd(int a,int b,int &x,int &y)
2 {
3 if(b==0)
4 {
5 x=1;
6 y=0;
7 return a;
8 }
9 int r=exGcd(b,a%b,x,y);
10 int t=x;
11 x=y;
12 y=t-a/b*y;
13 return r;
14 }
首先,我们看一下他是怎么形成的。从最后一层往上推:首先b=0 时得到最大公约数 a ,return a; 现在看上一层,从r那句后继续往下运行,可以知道,此后,每次都从r 句 获得已经得到的最大公约数,然后再往下执行。。。
规定 a' 、b' 是倒三层的,a、b是倒二层的
对于倒二层的a、b来说,有gcd(a,b) = x2*a + y2*b ; (x2=0,y2=1,因为这里b就是公约数)
对于倒三层的a'、b'来说,gcd(a',b') = x3*a' + y3*b' ;
将倒三层的a'和b' 代入倒二层:gcd(a,b) = x2*b' + y2*(a' % b') ;
----->因为gcd(a',b') = gcd(a,b)
----->所以 x3*a' + y3*b' = x2*b' + y2*(a' % b')
----->有:x3*a' + y3*b' = x2*b' + y2*(a' - a' / b' * b') 【很关键的一步:化解取模】
----->整理:x3*a' + y3*b' = y2*a' + (x2 - a' / b' * y2)*b'
----->有:x3=y2 、 y3=(x2 - a' / b' * y2)
----->两行代码的原因出来了:
----->这一层的x等于下一层的y 【就是 x=y; 这一句】
----->这一层的y等于下一层的x - a' / b' *y 【就是 y=t-a/b*y; 这一句】
这里虽然拿特例:倒二倒三层解释,但由于没有涉及具体的x、y值,所以得出的公式应该是通用的。 这解释了我们代码的写法原因,同时最后一层的a本身就是公约数,b为0,所以x1=1;y1=0;
采用递归写法先到底层,然后由底层的x、y逐步上推,得到顶层的x、y,就是我们想求的x、y。。。
......
注:扩展欧几里得算法可以用于求可逆元等问题中。