一、欧几里得算法
又称辗转相除法,设a,b为整数,gcd(a,b)=gcd(b,a mod b);
int gcd(int a,int b){ if(b==0)return a; return gcd(b,a%b); } // int gcd(int a,int b){ return b? gcd(b,a%b):a; }
二、线性组合
定理:gcd(a,b)是a,b的最小正线性组合,即gcd(a,b)=a*x+b*y;
三、扩展欧几里得算法
问题:如何求二中的x,y?
思路:
①if b==0,a!=0->可取x=1,y=0
②if a*b!=0;
由于gcd(a,b)=a*x+b*y;gcd(b,a mod b)=b*x'+(a-(a/b)*b)*y';
扫描二维码关注公众号,回复:
1025520 查看本文章
由于gcd(a,b)==gcd(b,a mod b),可以得到递推式子:
x=y'
y=x'-(a/b)*y'
可以发现(x,y)->(x',y')与(a,b)->(b,a mod b)是同步的
所以稍微修改gcd函数,使得在求得最大公约数的同时,递归可以求得x,y的一组解
int exgcd(int a,int b,int& x,int& y){ if(b==0){ x=1;y=0; return a; } int r=exgcd(b,a%b,x,y); int tx=x,ty=y; x=ty; y=tx-(a/b)*ty; return r; }
这里要特别说一下,如何的到x,y的通解。实际上,所有的(x0,y0)都可以得到无数组答案->(x0+b*k,y0-a*k)
但是这不是所有的答案,所有的答案应该是:(x0+b/gcd(a,b)*k,y0-a/gcd(a,b)*k)
四、扩展欧几里得算法求解不定方程
a*x+b*y=c有整数解的充要条件是gcd(a,b)|c
因为我们总可以得到gcd(a,b)=a*x'+b*y'
假如c=0(mod gcd(a,b)),那么只要等式两边同时乘以c/gcd(a,b),即得解
x=x'*c/gcd(a,b)
y=y'*c/gcd(a,b)
由于x*,y*有无数组,所以对应的x,y也有无数组
bool linear_equation(int a,int b,int c,int& x,int& y){ int d=exgcd(a,b,x,y); if(c%d)return false; int k=c/d; x*=k;y*=k; return true; }
五、扩展欧几里得算法求解同余方程
六、扩展欧几里得算法求解逆元