现在的位置: 首页 > 综合 > 正文

辗转相除

2018年02月20日 ⁄ 综合 ⁄ 共 1090字 ⁄ 字号 评论关闭

首先是我们常用的最大公约数

int gcd(int a,int b)

{

   if(b==0)return a;

   else return gcd(b,a%b);   

}

思想就是辗转相除,大数对小数取余,然后余数与较小数继续进行,直到一个为0,为止。

或是非递归。

int gcd(int x, int y){

   if (!x || !y) return x > y ? x : y;

   for (int t; t = x % y; x = y, y = t);

   return y;

}

辗转相除法又称欧几里德算法,用于计算两个整数a,b的最大公约数。其计算原理依赖于下面的定理:
  定理:gcd(a,b) = gcd(b,a mod b)
  证明:a可以表示成a = kb + r,则r = a mod b
  假设d是a,b的一个公约数,则有
  d|a, d|b,而r = a - kb,因此d|r
  因此d是(b,a mod b)的公约数
  假设d 是(b,a mod b)的公约数,则
 d | b , d |r ,但是a = kb +r
  因此d也是(a,b)的公约数

 

快速gcd通过减少乘除法以及基于一个这样的事实,若是某一个都是某个基值的整数倍,则他们最大公约数也是某个基值的整数倍。选取该基值为2可以通过位运算以及“降阶”(减少整数的大小)提高速度。

int kgcd(int a,int b){

   if(a==0)return b;

   if(b==0)return a;

   if(!(a&1)&&!(b&1))returnkgcd(a>>1,b>>1)<<1;

   else if(!(b&1))return kgcd(a,b>>1);

    else if(!(a&1))return kgcd(a>>1,b);

   else return kgcd(abs(a-b),min(a,b));

}

 

扩充欧几里得算法即扩充GCD就是求得x,y使得gcd(a,b)=ax+by(解一定存在的)

int extgcd(int a,int b, int & x, int & y){

if (b == 0) { x=1; y=0; return a; }

int d = extgcd(b, a % b, x, y);

int t = x; x = y; y = t - a / b * y;

return d;

x、y的复制过程就是计算每一步的a’x+b’y=gcd(a’,b’);系数过程

对于每一步,我们有a’=b,b’=a%b;a’x+b’y=gcd(a’,b’)由于b’=a%b=a-a/b*b

所以对于每一步,我们有a'x + b'y = Gcd(a', b') ===>

  bx + (a - a / b * b)y = Gcd(a', b') = Gcd(a, b)===>

  ay +b(x - a / b*y) = Gcd(a, b)

这样就可以递归回来得到x,y的值

抱歉!评论已关闭.