欧几里得算法-计算a,b最大公约数
计算方法
1.当b≠0时:a=b,b=a%b;
2.当b=0时,最大公约数为a;
算法
int gcd(int a,int b){
return !b?a:gcd(b,a%b);
}
扩展-计算ax+by=gcd(a,b)
方法(其中a,b是在不断变化的)
- 首先计算出gcd=gcd(a,b);
- ax1+by1=gcdax_{1}+by_{1}=gcdax1+by1=gcd且bx2+(a%b)y2=gcdbx_{2}+(a\%b)y_{2}=gcdbx2+(a%b)y2=gcd,所以ax1+by1=bx2+(a%b)y2ax_{1}+by_{1}=bx_{2}+(a\%b)y_{2}ax1+by1=bx2+(a%b)y2,又a%b=a−(a/b)∗ba\%b=a-(a/b)*ba%b=a−(a/b)∗b,所以整理得到ax1+by1=ay2+b(x2−(a/b)y2)ax_{1}+by_{1}=ay_{2}+b(x_{2}-(a/b)y_{2})ax1+by1=ay2+b(x2−(a/b)y2),所以x1=y2,y1=x2−(a/b)∗y2x_{1}=y_{2},y_{1}=x_{2}-(a/b)*y_{2}x1=y2,y1=x2−(a/b)∗y2;
- 这样通过递归计算就可以得到一组解x,yx,yx,y,此时显然a∗(x+s1)+b∗(y−s2)=gcda*(x+s_{1})+b*(y-s_{2})=gcda∗(x+s1)+b∗(y−s2)=gcd,化简得到s1/s2=b/a=(b/gcd)/(a/gcd)s_{1}/s_{2}=b/a=(b/gcd)/(a/gcd)s1/s2=b/a=(b/gcd)/(a/gcd),所以xall=x+b/gcd∗ki,yall=y−a/gcd∗ki,i=0,1,2,3,...x_{all}=x+b/gcd*k_{i},y_{all}=y-a/gcd*k_{i},i=0,1,2,3,...xall=x+b/gcd∗ki,yall=y−a/gcd∗ki,i=0,1,2,3,...,可以看出xall,yallx_{all},y_{all}xall,yall分别以b/gcd,a/gcdb/gcd,a/gcdb/gcd,a/gcd为周期,所以最小的正整数x=(x%(b/gcd)+(b/gcd))%(b/gcd)x=(x\%(b/gcd)+(b/gcd))\%(b/gcd)x=(x%(b/gcd)+(b/gcd))%(b/gcd),(这里是为了保证x为正整数,因为等式右侧的xxx可能为负数);
代码
int getgcd(int a,int b,int &x,int &y){//这里找出x,y与a和b的最大公约数
if(b==0){
x=1;
y=0;
return a;
}
int g = getgcd(b,a%b,x,y);//获得最大公约数
//递归找到最初的x与y
int temp=x;
x=y;
y=temp-(a/b)*y;
return g;
}
进一步扩展-计算ax+by=c
方法
- 首先我们计算ax+by=gcd(a,b)=gcdax+by=gcd(a,b)=gcdax+by=gcd(a,b)=gcd得xxx;
- 然后两边同时乘以c/gcdc/gcdc/gcd得ax∗(b/gcd)+by∗(b/gcd)=gcd∗(c/gcd)ax*(b/gcd)+by*(b/gcd)=gcd*(c/gcd)ax∗(b/gcd)+by∗(b/gcd)=gcd∗(c/gcd),(注意到c%gcd==0c\%gcd==0c%gcd==0才成立);
- 所以我们由上一个问题可以得到该问题的解xall=x∗(b/gcd)+b/gcd∗ki,yall=y∗(b/gcd)−a/gcd∗ki,i=0,1,2,3,...x_{all}=x*(b/gcd)+b/gcd*k_{i},y_{all}=y*(b/gcd)-a/gcd*k_{i},i=0,1,2,3,...xall=x∗(b/gcd)+b/gcd∗ki,yall=y∗(b/gcd)−a/gcd∗ki,i=0,1,2,3,...;
再次扩展-同余式计算
概念:
a与c模m同余:即(a-b)%m=0;可以写成:ax=c(mod m);
方法
- (ax−m)%c=0(ax-m)\%c=0(ax−m)%c=0,可以转化为ax+ck=max+ck=max+ck=m,这样就转化成为了上一个问题同样有m/gcd(a,m)=0m/gcd(a,m)=0m/gcd(a,m)=0。此时xall=x+(m/gcd)∗kx_{all}=x+(m/gcd)*kxall=x+(m/gcd)∗k其中,k的取值只能在0,1,…,m-1中取,否则会被在这个范围内的数取代.
再次扩展-逆元
概念
若a*b=1(mod m),即(a∗b)%m=1(a*b)\%m=1(a∗b)%m=1,这样即是同余式中的余数1;这里注意要求gcd(a,m)=1,否则无解,因为此时c/gcd(a,m)=1/gcd(a,m),由第二个问题可得,必然要求gcd(a,m)=1.
扩展
当模m为素数时,所要求的a*b=1(mod m),已知a,且a≠0,则b=am−1b=a^{m-1}b=am−1。