整理一下想法。
辗转相除法:
原理:设f(x,y)表示x,y的最大公约数,取k=x/y,b=x%y,那么x=ky+b。由此可得,如果一个数可以整除x和y,那么也可以整除y和b,即f(y,b)=f(x,y)。即f(x,y)=f(y,x%y)。
优点:高效
缺点:取模运算,开销大
辗转相减法:
原理:设f(x,y)表示x,y的最大公约数k,则可设x=mk,y=nk,则有x-y=(m-n)k,因为m和n都是正整数,则有x-y也可以被k整除,即f(x,y)=f(y,x-y)。
优点:开销小
缺点:入股市f(999999,1)就完蛋了
取2求素法:
原理:1、f(x,y)=k*f(x1,y1);2、如果x=p*x1,假设p是素数,并且y%p!=0,那么f(x,y)=f(p*x1,y)=f(x1,y)。
由此可得到算法为:不断的对x和y做除2操作,直至两者均不能被2整除,采用辗转相减法,获得一个可被2整除的数,继续做除2操作,循环,直至两数之一为0。详细描述如下:
若x,y均为偶数,f(x,y) = 2*f(x/2,y/2) = 2*f(x>>1,y>>1)
若x为偶数,y为奇数,f(x,y) = f(x/2,y) = f(x>>1,y)
若x为奇数,y为偶数,f(x,y) = f(x,y/2) = f(x,y>>1)
若x,y均为奇数,f(x,y) =f(y,x-y)
代码见下:
#include <stdio.h> #include <stdlib.h> #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif _Bool IsEven(int a) { if(a%2 == 0) return TRUE; else return FALSE; } int gcd(int x, int y) { printf(“gcd(%d,%d)/n”,x,y); if(x<y) return gcd(y,x); if(y==0) return x; if(IsEven(x)) { if(IsEven(y)) return (gcd(x >> 1, y >> 1) << 1); else return gcd(x >> 1, y); } else { if(IsEven(y)) return gcd(x, y >> 1); else return gcd(y,x-y); } } int main() { int x,y; scanf(“%d%d”,&x,&y); printf(“%d/n”,gcd(x,y)); system(“pause”); }