欧几里德算法中的Fibonacci序列

     首先,相信大家都已熟知欧几里德算法,此处不再赘述,只列算法如下:


gcd(a,b) { if(a < b) swap(a,b) while(b != 0) { r = a mod b a = b b = r } return a }


    忽略第三行和第四行,该算法仍能正确的求出a和b最大公因数,包括这两行只是为了简化对算法效率的分析。


    接着,让我们给出对该算法效率的分析,我们取while循环里的模运算为基本操作,可以证明:如果0到m(m>=8)之间不同时为0的一对整数作为欧几里德算法的输入,那么最多需要执行log3/2 (2m/3)次模运算。其时间效率为θ(log3/2 (2m/3)),与输入规模成线性关系(输入规模为表示m所用的位,即lgm+1)。

 

    上边的效率是怎么求出来的呢?首先让我们引入以下定理:当一对数a、b(a>b)作为欧几里德算法的输入时,需要执行n(n>=1)次模运算,那么a>=fn+2 ,且b>=fn+1 ,其中{fn }代表Fibonacci序列。然后我们简单证明欧几里德算法的时间效率为θ(log3/2 (2m/3)):由以上给定定理,可得fn+2 <=a<=m;又由m>=8知n>=4,故n+2>=6;因为当n>=6时,(3/2)n-1 <=fn (使用数学归纳法可证明,此处略去不证),故有(3/2)n+1 3/2 m-1= log3/2 (2m/3)。证毕。


    现在回过来看定理“当一对数a、b(a>b)作为欧几里德算法的输入时,需要执行n(n>=1)次模运算,那么a>=fn+2 ,且b>=fn+1 ,其中{fn }代表Fibonacci序列”。该定理同样可用数学归纳法证明,此处不进行证明。也许你会疑问,为什么这里会涉及到Fibonacci序列?

 

    为了解开疑问,让我们来观察欧几里德算法,该算法依赖于如下事实:如果a是一个非负整数,b是一个正整数,r=a mod b,那么gcd(a,b)=gcd(b,r)。其基本思路就是通过取模运算不断使用更小的b和r来代替a和b,即使a和b不断减小。假设a>b,则a=bq+r,其中q>=1,0<=r

 

    明白了欧几里德算法的基本思想,让我们来考虑该算法的最坏情况,即何时会使上述a、b的减小最少?对,就是当q=1时,此时每次模运算减小规模最少。现在设想每次取模时q都等于1,会怎样呢?对,我们会得到一个Fibonacci序列。如,把13和8作为欧几里德算法的输入,则模运算前和各次模运算后得到的数对如下:(13,8)、(8,5)、(5,3)、(3,2)、(2,1)、(1,0)。把每两个紧挨的数对中重复的元素和0元素去掉,则正好得到Fibonacci序列从第二项开始的部分。也就是说,当欧几里德算法的输入是Fibonacci序列中连续的两项时,算法执行时间是同等规模下的最坏情况执行时间。现在揭开我们前边的疑问:为什么定理“当一对数a、b(a>b)作为欧几里德算法的输入时,需要执行n(n>=1)次模运算,那么a>=fn+2 ,且b>=fn+1 ,其中{fn }代表Fibonacci序列”中会出现a>=fn+2 、b>=fn+1 ?因为Fibonacci序列让欧几里德算法运行的如此之慢,以至于任何其他需要相等次模运算的情况,都可以处理规模更大的数对。


    相信现在大家已经对欧几里德算法中的Fibonacci序列有了足够认识,它是欧几里德算法最坏情况的输入。

 

你可能感兴趣的:(algorithm)