Fibonacci(矩阵的幂实现)
Fibonacci数列: 1, 1, 2, 3, 5, 8, 13, 21, …
增加 F0=0,得到数列 0,1, 1, 2, 3, 5, 8, 13, 21, …
问题:已知 F0=0, F1=1, 给定n, 利用矩阵的乘法计算 Fn.
算法步骤:
通过观察我们不难发现fibonacii数列矩阵的特殊性:N个{{1,1}{1,0}}矩阵相乘得到的右下角数为第N位fibonacii数。(即要得到N位fibonacii数就要使用N位矩阵连乘)
为了减少连乘次数我们可以使用动态规划算法。但是,这个连乘数列有特殊性:(他的所有矩阵都相同),所以我采取以下方法完成:
首先使用递归算法使之两两相乘(如:(A1A2)(A3A4)(A5A6))但是在这里我们只计算一次:即只计算(A1,A2)因为后两个(A3A4)(A5A5)的结果和(A1A2)相同。
合并后(A1A2)(A3A4)(A5A6))记为(B1,B2,B3),为单数,那么我们只要在最后一个数之前使用之前方法只相乘一次,全部结束后再乘以最后未乘的矩阵。大大减少相乘次数(6位矩阵乘3次、乘法24次;12位乘4次、乘法32次)
#include<iostream.h>
struct Array
{
int A[2][2];
};
Array Multi(Array x,Array y)
{
Array z;
z.A[0][0]=(x.A[0][0]*y.A[0][0])+(x.A[0][1]*y.A[1][0]);
z.A[0][1]=(x.A[0][0]*y.A[0][1])+(x.A[0][1]*y.A[1][1]);
z.A[1][0]=(x.A[1][0]*y.A[0][0])+(x.A[1][1]*y.A[1][0]);
z.A[1][1]=(x.A[1][0]*y.A[0][1])+(x.A[1][1]*y.A[1][1]);
return z;
}
Array Fibonacci(Array d,int n)
{
Array h,q;
if(n==1)
return d;
if(n%2==0)
{
h=Multi(d,d);
n=n/2;
q=Fibonacci(h,n);
}
else
{
h=Multi(d,d);
n=n/2;
q=Fibonacci(h,n);
q=Multi(q,d);
}
return q;
}
void main()
{
Array x,y;
x.A[0][0]=1;x.A[0][1]=1;
x.A[1][0]=1;x.A[1][1]=0;
for(int i=1;i<=30;i++)
{
y = Fibonacci(x,i);
cout<<y.A[1][1]<<"\t";
if(i%10==0)
cout<<endl;
}
}