关于欧几里得算法及其扩展

一、欧几里得算法(辗转相除法)

 

 1、问题:求解两个非负整数a、b的最大公约数。

 2、算法理解:假设整数d是a、b的公约数,即d能整除a和b。令r=a%b(a对b取余),则d也是r的一个约数。理解为a中除去b的整数倍部分,剩余的部分也一定是d的整数倍。因为d既是b的约数,又是r的约数,所以d是b和r的公约数!由于这里的d是一般假设的,所以可知a和b所有的公约数d都是b和r的公约数,所以b和r的最大公约数一定就是a、b的最大公约数。将b、r作为新的a、b,按此规律层层下剥,最后当a能整除b,则它的下一次a,b两个数变成b和0,最大公约数便是此时的b了。

 

 3、Java代码实现:

 /**
* 返回两个非负整数的最大公约数。
* @param num1
* @param num2
* @return
*/
public static int operation1(int num1,int num2){
if(num2==0)//分母为0,则分子num1为最大公约数。
return num1;
int r=num1%num2;
return operation1(num2,r);//num2和r的最大公约数即为原num1和num2的最大公约数。
}

上述方法体更简洁的写法是:
return num2==0?num1:operation1(num2,num1%num2);

根据辗转相除的思想也可用循环实现:
public static int operation2(int num1,int num2){
if(num2==0)
return num1;
int r;//余数。
while(num2!=0){
r=num1%num2;//num2和r的最大公约数即为原num1和num2的最大公约数。
num1=num2;
num2=r;
}
return num1;
}

二、扩展欧几里得算法

 1、问题:

 一句话,求满足条件:ax+by=r的x、y的值,其中a、b为不全为0非负整数,r为a和b的最大公约数,

 x、y均为整数。

 2、算法理解:

  设ax1+by1=gcd(a,b)=r,由欧几里得算法则有bx2+(a%b)y2=gcd(b,a%b)=r,因为等式右边r保持不变,

 便有:ax1+by1=bx2+(a%b)y2

又a%b=(a-[a/b]*b), 其中[a/b]表示a/b结果取整,所以上式

 变为:ax1+by1=bx2+(a-[a/b]*b)y2,

 整理得:ax1+by1=ay2+b(x2-[a/b]),两边对应起来,

 则有:x1=y2,y1=x2-[a/b]

  由欧几里得算法逐次递归下去,每“相邻”两层都会满足上述等式关系,由于最后一层有等式:

  ax+by=r,其中b=0,r=a,得出:x=1,y=0。

 从最后依次回代入上一层,最终便可得出x1,y1的值,有此也可知,x1,y1的值是唯一的

 3、Java代码实现:

  public static int gcdExtends(int num1,int num2){
if(num2==0){
x=1;
y=0;
return num1;
}
int r=gcdExtends(num2,num1%num2);
int temp=x;
x=y; //由公式演算可得“相邻”两组x、y的关系。
y=temp-num1/num2*y;
return r;
}

 

 

 


 

 

你可能感兴趣的:(算法)