《编程之美》2.7 最大公约数问题

整理一下想法。

 

辗转相除法:

原理:设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求素法:

原理:1f(x,y)=k*f(x1,y1)2、如果x=p*x1,假设p是素数,并且y%p!=0,那么f(x,y)=f(p*x1,y)=f(x1,y)

由此可得到算法为:不断的对xy做除2操作,直至两者均不能被2整除,采用辗转相减法,获得一个可被2整除的数,继续做除2操作,循环,直至两数之一为0。详细描述如下:

xy均为偶数,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)

xy均为奇数,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”); }  

    原文作者:kaytowin
    原文地址: https://blog.csdn.net/kaytowin/article/details/5112952
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞