用矩阵快速幂求解递推数列的第n项

斐波那契数列

  • 每一项的数字等于前两项的和,
  1. 递推公式
  2. 矩阵形式

击鼓传花

  • 题目描述:
    一共有k个人, 每一次可以把自己手中的花传给其它任何一个人, 初始时在自己手中, 求M次后有多少种方式回到自己手中
  1. 递推公式
    表示第次在自己手中, 表示第次不在自己手中,
  2. 矩阵形式

求数列的第n项

  1. 递推公式

  2. 矩阵形式
    [f_i, f_{i-1}, f_{i-2}, (i+1)^2, i+1, 1] = [f_{i-1}, f_{i-2}, f_{i-3}, i^2, i, 1] * \begin{bmatrix} a & 1 & 0 & 0 & 0 & 0\\ b & 0 & 1 & 0 & 0 & 0\\ c & 0 & 0 & 0 & 0 & 0\\ 2 & 0 & 0 & 1 & 0 & 0\\ -1 & 0 & 0 & 2 & 1 & 0\\ 32767 & 0 & 0 & 1 & 1 & 1 \end{bmatrix}
    首先将向量改写成的形式, 即向量中只有系数为1数列的前几项或者的多项式, 然后待定系数求转移矩阵

矩阵快速幂的参考代码


public class MatQuickPower {

    public static final int MOD = 1_000_000_007;

    public static int[][] matQuickPower(int [][]a, int k) {
        if (k == 1) return a;
        int [][]tmp = matQuickPower(a, k >> 1);
        if ((k & 1) == 0) return matmul(tmp, tmp);
        else return matmul(matmul(tmp, tmp), a);
    }

    public static int[][] matmul(int [][]a, int [][]b) {
        int [][]c = new int[a.length][b[0].length];
        for (int i = 0; i < a.length; i++) {
            for (int j = 0; j < b[0].length; j++) {
                for (int k = 0; k < a[i].length; k ++){
                    c[i][j] = (int) ((c[i][j] + (long)(a[i][k] % MOD) * (long)(b[k][j] % MOD)) % MOD);
                }
            }
        }
        return c;
    }

}

你可能感兴趣的:(用矩阵快速幂求解递推数列的第n项)