Fibonacci Numbers

阅读TAOCP中Fibonacci Numbers内容后的想法。

Fibonacci Numbers,形如以下的数列 
0,1,1,2,3,5,8,13,21,34, … , 
在这个数列中从第三项开始,每一个元素都是前两个元素的和。 
可以写成以下形式: 

formula1:

F0 = 0; F1 = 1; Fn+2 = Fn+1 + Fn , n>=0. 
由此我们就可以得到递归代码:

int Fibonacci_Numbers(int n)
{
	if(n==0)
		return 0;
	if(n==1)
		return 1;
	return Fibonacci_Numbers(n-1)+Fibonacci_Numbers(n-2);
}

对于上面的算法,经历的时间是指数级的
通过模拟上面的过程可以发现有许多状态是重复的。
我们可以改进上面的过程,改用递推的方式。将原来的状态保留下来,便于以后的使用。
int Fibonacci_Numbers(int n)
{
	int FibNum[MAXSIZE]={0,1};
	for(int i=2;i<=n;++i)
	{
		FibNum[i]=FibNum[i-1]+FibNum[i-2];
	}
	return FibNum[n];
}
经过此番改进我们可以得到时间复杂度为O(n)的算法。
但是我们通过另一个关于 Fibonacci Numbers表达式可以得到另一个算法。

formula2

该数学形式表示为:Fn+1 * Fn-1 - Fn= (-1),
当我们该等式转化为矩阵的形式(此处还不太会数学符号的插入),我们得到一个求解 Fibonacci Numbers的可能更有效的 算法。
int Fibonacci_Numbers_Matrix(int n)
{
	int FibNumMat[2][2]={1,1,1,0};
	int FibNumAns[2][2]={1,1,1,0};
	if(n==0)
		return 0;
	if(n==1||n==2)
		return 1;
	for(int i=0;i<n-2;++i)
	{
		int a=FibNumAns[0][0],b=FibNumAns[0][1];
		int c=FibNumAns[1][0],d=FibNumAns[1][1];
		FibNumAns[0][0]=a*FibNumMat[0][0]+b*FibNumMat[1][0];
		FibNumAns[0][1]=a*FibNumMat[0][1]+b*FibNumMat[1][1];
		FibNumAns[1][0]=c*FibNumMat[0][0]+d*FibNumMat[1][0];
		FibNumAns[1][1]=c*FibNumMat[0][1]+d*FibNumMat[1][1];
	}
	return FibNumAns[0][0];
}
当我们改进成上面的程序时发现并不会比O(n)的算法更优。
如果将 n 表示成 n = b 0*2 0  + b 1*2 1  + b 2*2 2  + ...+ b n*2 .
可以得到一些启示,将上面的程序写成这样子:
int Fibonacci_Numbers(int n)
{
	int FibNumMat[2][2]={1,1,1,0};
	int FibNumAns[2][2]={1,0,0,1};
	while(n>0)
	{
		if(n&1)
			Matrix((int *)FibNumAns,(int *)FibNumMat),n--;
		else
			Matrix((int *)FibNumMat,(int *)FibNumMat),n>>=1;
	}
	return FibNumAns[0][1];
}
void Matrix(int *Mat1,int *Mat2)
{
	int a1=*Mat1,b1=*(Mat1+1),c1=*(Mat1+2),d1=*(Mat1+3);
	int a2=*Mat2,b2=*(Mat2+1),c2=*(Mat2+2),d2=*(Mat2+3);
	*Mat1=a2*a1+c2*b1;
	*(Mat1+1)=b2*a1+d2*b1;
	*(Mat1+2)=a2*c1+c2*d1;
	*(Mat1+3)=b2*c1+d2*d1;
}
                         http://blog.csdn.net/liuzhanchen1987/article/details/7712640  
此处的时间复杂度应该是O(logn),所用算法思想类似快速幂取模。
此外在书中还有一些有趣的式子。

1 ) F n+m  = F n*F n+1  + F m-1*F n.
 如果转化为 F n  = F n/2*F n/2+1  + F n/2-1*F n/2. 会不会有时间复杂O(logn)的算法。

2)GCD(F m  , F n)=F GCD( m , n ).

3 )  F m*n+r  = F r                                if m mod 4 = 0.
      Fm*n+r = (-1)r+1*Fn-1             if m mod 4 = 1.
      Fm*n+r = (-1)r*Fr                      if m mod 4 = 2.
      F m*n+r  = (-1) r+1+n*F n-r           if m mod 4 = 3.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值