程序设计实习递归练习 矩阵快速幂求斐波那契数列

程序设计实习递归练习 矩阵快速幂求斐波那契数列

这是来自程序设计实习课堂上的趣味练习,非常有意思,而且矩阵快速幂也是早该掌握的方法。

趣味思考题:菲波那契数列的计算
递归:O(N)
递推:O(N)
问题:给出一种时间复杂度低于O(N)的解法,例如O(log2 N)甚至O(1)?
当N=2的60次方时如何计算?

选自《编程之美——微软技术面试心得》

除了矩阵快速幂还有其他方法。比如直接快速幂,其中sqrt(5)当作符号保留,复杂度O(log2 n)。如果数据较小,不必担心精度,可以直接计算幂次,用取对数计算,复杂度O(1)。

运用矩阵乘法描述递推关系,这样就可以实现把下标增长转化为矩阵的幂次,再快速幂加速
递推方程式为 (a(n+1),a(n+2))’=((0,1),(1,1))* (a(n),a(n+1))’=(a[1])^n*(1,1)’

类似的题目还有高精度幂次快速幂——麦森数以及所有递推公式的方法

#define MAX_N 10

#include<stdio.h>

//(a(n+1),a(n+2))'=((0,1),(1,1))*(a(n),a(n+1))'=(a[1])^n*(1,1)'

int a[MAX_N+1][2][2]={{{1,0},{0,1}},{{0,1},{1,1}}};
int n;

void cal(int n)
{
    if (a[n][0][0]+a[n][0][0]+a[n][1][0]+a[n][1][1])
        return;
    if (n==1 || n==0)
        return;
    int i1=n>>1,i2=n-i1;
    cal(i1);
    cal(i2);
    for (int k=0;k<2;k++)
        for (int i=0;i<2;i++) 
            for (int j=0;j<2;j++)
                a[n][i][j]+=a[i1][i][k]*a[i2][k][j];
    return;
}

int main()
{
    for (int n=1;n<=MAX_N;n++)
    { 
        cal(n-1);
        printf("f(%d)=%d\n",n,a[n-1][1][1]);
    }
    return 0;
}

你可能感兴趣的:(程序设计实习递归练习 矩阵快速幂求斐波那契数列)