前置知识——欧几里得算法
循环实现:
int gcd(int a, int b){
int tmp;
while(b){
tmp = a % b;
a = b;
b = tmp;
}
return a;
}
1
2
3
4
5
6
7
8
9
递归实现
int gcd(int a, int b){
return b == 0? a : gcd(b, a % b);
}
1
2
3
贝祖定理
定义
贝祖定理又称裴蜀定理 (Bezoutsidentity)
对于任意的不全为 0 的非负整数对 a,b ,一定存在整数 x,y 满足:a∗x+b∗y=(a,b)
证明
在 exgcd 最后一步中, (b=0)⇒(x=1,y=0) ,一定成立
b=0 的时候
假设 x0,y0 是 b×x+(a%b)y=(a,b) 的一组解(下一步)
即 b∗x0+(a%b)×y0=(a,b)
那么只要能证明 a×x1+b×y1=(a,b) 成立即可(本步)
易得 a%b=a−⌊ba⌋×b ,那么
=⇒bx0+(a−⌊ba⌋×b)×y0ay0+b(x0−⌊ba⌋×y0)ax1+by1=(a,b)(x1=y0,y1=x0−⌊ba⌋×y0)
**定理得证**
通解的求法
ax+byy=c=bc−ax
我们设 (x0,y0) 是一组已知解
x1=x0+n
那么
y1=bc−a(x0−n)=bc−ax0−ban=y0−ban=yo−(a,b)b(a,b)an
可知,当 n≡0(mod(a,b)b) 解就一定存在
即对于任意整数 k :
⎩⎪⎪⎪⎨⎪⎪⎪⎧x1=x0+k(a,b)by1=y0−k(a,b)a
扩展欧几里得算法
代码思路
本质与欧几里得流程类似,都是个递归函数
设置递归出口,即上面说的“最后一步”,同时做出最后一步的东西:{x = 1, y = 0; return a;}
递归的本质是欧几里得,所以d = exgcd(b, a % b, x, y);
回溯,利用上面裴蜀定理证明过程的到的公式: x1=y0,y1=x0−⌊ba⌋y0 后续遍历(回溯)求 (x,y)
我们即然求出来了 (a,b) 那么就可以用它,在最后一步进行return d;
,得到 (a,b)
程序
int ex_gcd(int a, int b, int &x, int &y){
if(b == 0) { x = 1, y = 0; return a; }
int d = ex_gcd(b, a % b, x, y);
int tmp = x;
x = y;
y = tmp - (a / b) * y;
return d;
}
1
2
3
4
5
6
7
8
9
10
11