矩阵快速幂求解斐波那契系列问题

本文介绍了如何使用矩阵快速幂方法解决斐波那契数列的求解问题,通过分析递归关系,将时间复杂度降低到O(logN)。详细解释了矩阵快速幂的工作原理,并给出了具体的代码实现。

矩阵快速幂求解斐波那契问题

问题

​ 求解斐波那契数列第N​N​N

分析

​ 对于求第NNN项的值,可通过矩阵快速幂将时间复杂度降至O(logN)O(logN)O(logN)。递归式F(N)=F(N−1)+F(N−2)F(N)=F(N-1)+F(N-2)F(N)=F(N1)+F(N2),是一个二阶的递推数列,可用矩阵乘法表示,且状态矩阵为2×22\times 22×2的矩阵:
(F(n),F(n−1))=(F(n−1),F(n−2))× ∣abcd∣(F(n), F(n-1)) = (F(n-1),F(n-2)) \times \ \left| \begin{array}{cc} a & b\\ c & d\\ \end{array} \right| (F(n),F(n1))=(F(n1),F(n2))× acbd
把前4项代入,F(1)==1,F(2)==1,F(3)==2,F(4)==3F(1) == 1, F(2) == 1, F(3) == 2, F(4) == 3F(1)==1,F(2)==1,F(3)==2,F(4)==3,可求出状态转移矩阵:
∣abcd∣=∣1110∣ \left| \begin{array}{cc} a & b\\ c & d\\ \end{array} \right| = \left| \begin{array}{cc} 1 & 1 \\ 1 & 0 \\ \end{array} \right| acbd=1110
n>2n > 2n>2时,
(F(3),F(2))=(F(2),F(1))× ∣1110∣=(1,1)×∣1110∣(F(4),F(3))=(F(3),F(2))×∣1110∣=(1,1)×∣1110∣2⋮(F(n),F(n−1))=(F(n−1),F(n−2))×∣1110∣=(1,1)×∣1110∣n−2(F(3), F(2)) = (F(2),F(1)) \times \ \left| \begin{array}{cc} 1 & 1\\ 1 & 0\\ \end{array} \right| = (1, 1) \times \left| \begin{array}{cc} 1 & 1\\ 1 & 0\\ \end{array} \right| \\ (F(4), F(3)) = (F(3),F(2)) \times \left| \begin{array}{cc} 1 & 1\\ 1 & 0\\ \end{array} \right| = (1, 1) \times \left| \begin{array}{cc} 1 & 1\\ 1 & 0\\ \end{array} \right|^2 \\ \vdots \\ (F(n), F(n-1)) = (F(n-1),F(n-2)) \times \left| \begin{array}{cc} 1 & 1\\ 1 & 0\\ \end{array} \right| = (1, 1) \times \left| \begin{array}{cc} 1 & 1\\ 1 & 0\\ \end{array} \right|^{n-2} (F(3),F(2))=(F(2),F(1))× 1110=(1,1)×1110(F(4),F(3))=(F(3),F(2))×1110=(1,1)×11102(F(n),F(n1))=(F(n1),F(n2))×1110=(1,1)×1110n2
​ 所以,求解原问题转变为如何求解矩阵的NNN次幂,这就可以利用矩阵快速幂,时间复杂度为O(logN)O(logN)O(logN)。矩阵快速幂与普通快速幂并无本质区别,只是把普通乘法换成了矩阵乘法。下面举个例子说明普通快速幂如何快速计算。

​ 假设求解10的75次方:

​ 1.75的二进制数形式为1001011。

​ 2.10的75次方为1064×108×102×10110^{64}\times 10^8 \times 10^2 \times 10^11064×108×102×101

​ 我们先求出10110^1101,然后根据10110^1101求出10210^2102,再根据10210^2102求出10410^4104..................,最后根据103210^{32}1032求出106410^{64}1064。也就是说,75二进制表示有多少位,我们就做了多少次乘法。

代码

public int[][] matrixPower(int[][] m, int p){
    int[][] res = new int[m.length][m[0].length]; 
    //先把res初始化为单位矩阵
    for (int i = 0; i < res.length; i++){
        res[i][i] = 1;
    }
    int[][] tmp = m;
    for (; p != 0; p >>= 1){ //右移符号,相当于整除2
        if ((p&1) != 0){
            res = muliMatrix(res, tmp);
        }
        tmp = muliMatrix(tmp, tmp);
    }
    return res;
}

public int[][] muliMatrix(int[][] m1, int[][] m2){
    int[][] res = new int[m1.length][m2[0].length];
    for (int i = 0; i < m2[0].length; i++){
        for (int j = 0; j < m1.length; j++) {
            for (int k = 0; k < m2.length; k++){
                res[i][j] += m1[i][k] * m2[k][j];
            }
        }
    }
    return res;
}

使用矩阵快速幂求解斐波那契数列第NNN项的过程如下:

public int calc(int n){
    if (n < 1) {
        return 0;
    }
    if (n == 1 || n == 2){
        return 1;
    }
    int[][] base = {{1, 1} , {1, 0}};
    int[][] res = matrixPower(base, n - 2);
    return res[0][0] + res[1][0];
}

总结

​ 如果递归式严格符合F(n)=a×F(n−1)+b×F(n−2)+...+k×F(n−i)F(n) = a \times F(n-1) + b\times F(n-2) + ... + k\times F(n-i)F(n)=a×F(n1)+b×F(n2)+...+k×F(ni),那么它就是一个iii阶的递推式,必然有与i×ii \times ii×i的状态矩阵有关的矩阵乘法的表达。一律可用矩阵快速幂将时间复杂度降至 O(logN)O(logN)O(logN)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值