最大公约数(欧几里得算法)

            欧几里德算法(Euclid)阐述了一种gcd算法。gcd(greatest common divisor),简言之,我们想求gcd(x,y),假设(x>y),如果存在下式:x =  q*y + r,那么则有gcd(x,y) = gcd(y,r) ,其实上式也称为gcd递归定理,即gcd(a,b) = gcd (b,a mod  b)。另:最小公倍数=两整数的乘积÷最大公约数

1.最简单的gcd算法:

int gcd(int x, int y)
{
     if(y == 0) return x;    
     if(x < y)      return gcd(y,x);    
     else        return gcd(y, x%y); //或者是return gcd(x - y, y); 这样的话优化了大数据取模的问题,但是运算次数会增大
} 

2.ACM中常用的gcd算法:(程序只有一句话,讲真啊,算法博大精深啊)

int gcd(int a, int b){ return a == 0 ? b : gcd(b % a, a); } 

3.解法二的不足之处在于复杂的大数据除法运算,解法一虽然可以干掉了大数据的除法运算,但是增加了操作次数。两种方法都不是非常的完美,那么我们就用第三种方法来解决,第三种方法使用的二进制方案,
对于x,y来说,有x=k * x1,y = k * y1 ,则f(x ,y) = f(k * x1,k * y1) = k * f(x1 ,y1);此为公式一。
另外,如果 x = p * x1,且p为素数,y%p != 0,则f(x ,y)= f(p * x1, y) = f(x1 ,y);此为公式二。
由一和二两个公式,我们可以计算公约数了:
设p=2:
假设x,y都是偶数:f(x,y)= 2f(x»1,y»1);(因为除以二相当于位运算中的右移)
假设x是偶数,y是奇数:f(x,y) = f(x»1,y);
假设x是奇数,y是偶数:f(x,y) = f(x,y»1);
假设x,y都是奇数:f(x,y) = f(y,x-y);—这是根据解法一中推出来的
下面还以42 和 30 为例:
f(42,30) = f(101010,11110) = 2f(10101,1111) = 2f(1111,110)=2 * f(1111,11) = 2 f (1100,11) = 2f(110,11)=2 f(11,11) = 2 f(0,11) = 2 *3=6
括号中均为二进制表达,这样最坏的情况下,复杂度也就是log 2(max(x,y));———2是底数,尼玛,这格式弄不出来。

int gcd(int x,int y )
{
    if(x < y) return gcd(y,x);  // x>y
    if( y == 0) return x;  // if y=0, x is GCD 
    else
    {
         if( !(x%2) )
         {                 
           if( !(y%2) )  //x,y都为偶数
               return 2*gcd(x >> 1, y >> 1);    
           else      // x 是偶数, y是奇数
               return gcd(x >> 1, y );  
         }
         else 
         {
           if( !(y%2) )  // x是奇数 y是偶数
               return gcd(x, y >> 1);
           else       // x, y 都是奇数
               return gcd(y,x-y); 
         }
    }
}


你可能感兴趣的:(【模板】)