标签:span text 最大 -- nal cas 语法 位置 辗转相减
深根半夜里研究C++的语法,在弄到关于函数的定义 这一部分时突然想写个试试,就拿比较熟悉的gcd来好了。
活这么久gcd一直是用辗转相除法(或者说欧几里得算法)得出的,根据《算法导论》第三版的中文页码P547给出的伪代码,很容易就得出C++的写法。
int gcd(int a,int b){
if(b==0)
return a;
else
return gcd(b,a % B);
}
However----
当a,b比较大的时候显得特别慢,所以出现了来自《九章算术》中的更相减损术来求gcd。(怕是活久见的实例。。。)
更相减损术的代码如下:
int gcd(int a,int b){
if(a==b)
return a;
else
if(a<b)
return gcd(b-a,a);
else
return gcd(a-b,b);
}
换句话说,其原理可以被称为“辗转相减法”【笑】。根据gcd(a,b)=gcd(|a-b|,min(a,b)),然后设定一下边界(即两个相等的数,其gcd值为本身),就有了。具体证明不知道【喂太草率了吧!!】,反正没问题可以用就是了。
But----
当|a-b|比较大的时候,很明显递归次数比较多,这不是想要的结果。再看一遍原文:
可半者半之,不可半者,副置分母、子之数,以少减多,更相减损,求其等也。以等数约之。
好了,【作为一名文科生恬不知耻地笑了】其实原文的目的是为了约分,“可半者半之”就是说能约2就约2,然后不能约2了再找gcd约分。
所以分类讨论一下:
所以ok,final版本的gcd就出来了,大半夜的写错了别打我啊。。。
int gcd(int a,int b){
if(a==b)
return a;
else
switch (check(a,b)){
case 0:return 2*gcd(a/2,b/2);break;
case 1:return gcd(a,b/2);break;
case 2:return gcd(a/2,b);break;
case 3:return gcd(abs(a-b),min(a,b));break;
}
}
有必要说明一下的是check函数检验的是将要参与gcd运算的两数的奇偶性,0就是同偶,1和2都是一奇一偶只不过位置有区别,3就是同奇的情况;abs是绝对值函数,min则返回两数间较小的一个。
标签:span text 最大 -- nal cas 语法 位置 辗转相减
原文地址:http://www.cnblogs.com/mojibake/p/7296701.html