- 辗转相除法:
原理:
gcd ( x , y ) = gcd ( y , x m o d y ) \gcd(x,y) = \gcd(y,x \bmod y) gcd(x,y)=gcd(y,xmody)
证明:
设 z z z 为 x , y x,y x,y 的最大公约数。
有 z ∣ x , z ∣ y z|x \text{ , } z|y z∣x , z∣y ,则 z ∣ ( y − x ) z|(y-x) z∣(y−x) 。
所以:
gcd ( x , y ) = gcd ( x , x − k × y ) = gcd ( y , x m o d y ) ( k × y ≤ x < ( k + 1 ) × y ) \gcd ( x , y ) = \gcd ( x , x- k \times y) = \gcd ( y , x \bmod y) (k \times y \le x <(k+1) \times y) gcd(x,y)=gcd(x,x−k×y)=gcd(y,xmody)(k×y≤x<(k+1)×y)
当 x < y x<y x<y 时:
x m o d y = x x \bmod y = x xmody=x
所以:
gcd ( x , y ) = gcd ( y , x ) \gcd (x , y ) = \gcd (y,x) gcd(x,y)=gcd(y,x)
当 y < x y<x y<x 时:
gcd ( x , y ) = gcd ( y , x m o d y ) \gcd(x,y) = \gcd(y,x \bmod y) gcd(x,y)=gcd(y,xmody)
当 y = = 0 y==0 y==0 时,答案为 x x x 。
int gcd(int x,int y)
{
return y==0?x:gcd(y,x%y);
}
- 二进制算法:
通过不断筛去因子 2 2 2 来提高效率。
若 x = y x=y x=y ,则 gcd ( x , y ) = x \gcd (x,y) =x gcd(x,y)=x ,否则:
若 x , y x,y x,y 为偶数,则 gcd ( x , y ) = 2 × gcd ( x / 2 , y / 2 ) \gcd (x,y) =2 \times \gcd (x/2,y/2) gcd(x,y)=2×gcd(x/2,y/2)
若 x x x 为偶数, y y y 不为偶数,则 gcd ( x , y ) = gcd ( x / 2 , y ) \gcd (x,y) = \gcd(x/2,y) gcd(x,y)=gcd(x/2,y)
若 y y y 为偶数, x x x 不为偶数,则 gcd ( x , y ) = gcd ( x / 2 , y ) \gcd (x,y) = \gcd(x/2,y) gcd(x,y)=gcd(x/2,y)
若 x , y x,y x,y 均不为偶数,则 gcd ( x , y ) = gcd ( x − y , y ) \gcd(x,y)= \gcd (x-y,y) gcd(x,y)=gcd(x−y,y)
int GCD(int x,int y)
{
if(x==0)return y;
if(y==0)return x;
int i=0,j=0;
for(; (x&1)==0; i++)x>>=1;
for(; (y&1)==0; j++)y>>=1;
i=min(i,j);
while(1)
{
if(x<y)swap(x,y);
if(0==(x-=y))return y<<i;
while((x&1)==0)x>>=1;
}
}