没有条件转移的严格递推式,求第N项的结果,都有logN的时间复杂度的方式。
    如:斐波那契数列的严格递推公式为:
    15. 矩阵快速幂技巧 - 图1

    当含有条件转移的递推式,求第N项的结果,没有logN时间复杂度的方式
    eg:
    当为true时,为一个计算公式:
    当为false时,为另外一个计算公式

    线性代数解决严格递归,第几个项的问题

    斐波那契数列减的最多项为2,为2阶递推,则会存在一个二阶base矩阵,对于下列任意一项都满足

    15. 矩阵快速幂技巧 - 图2
    15. 矩阵快速幂技巧 - 图3
    15. 矩阵快速幂技巧 - 图4
    …….
    15. 矩阵快速幂技巧 - 图5
    将第一个式子中的 |F3,F2| 带入到 第二个式子|F3,F2|中,依次带入第三个,一直到带入最后一个式子中,得到最后结果为:
    15. 矩阵快速幂技巧 - 图6

    则只要求出 15. 矩阵快速幂技巧 - 图7矩阵的m次幂,则就可以推出第n项的值。

    如何求一个常数的n次幂,如15. 矩阵快速幂技巧 - 图8,75=64+8+2+1用二进制表示为:1001011
    15. 矩阵快速幂技巧 - 图9 = 1 15. 矩阵快速幂技巧 - 图1015. 矩阵快速幂技巧 - 图1115. 矩阵快速幂技巧 - 图1215. 矩阵快速幂技巧 - 图13

    同理对于一个矩阵|A|求其75次幂,按照上述规则,将1换成单位矩阵,10换成矩阵A即可。

    题目1:
    斐波那契数列求解第N项, LogN的时间复杂度。

    1. // ################################# 题目1 斐波那契 #####################
    2. public static int f1(int n) {
    3. if (n < 1) {
    4. return 0;
    5. }
    6. if (n == 1 || n == 2) {
    7. return 1;
    8. }
    9. return f1(n - 1) + f1(n - 2);
    10. }
    11. public static int f2(int n) {
    12. if (n < 1) {
    13. return 0;
    14. }
    15. if (n == 1 || n == 2) {
    16. return 1;
    17. }
    18. int res = 1;
    19. int pre = 1;
    20. int tmp = 0;
    21. for (int i = 3; i <= n; i++) {
    22. tmp = res;
    23. res = res + pre;
    24. pre = tmp;
    25. }
    26. return res;
    27. }
    28. // O(logN) 矩阵快速幂技巧.求斐波那契额数列
    29. public static int f3(int n) {
    30. if (n < 1) {
    31. return 0;
    32. }
    33. if (n == 1 || n == 2) {
    34. return 1;
    35. }
    36. // 数学计算求出base矩阵,
    37. int[][] base = {
    38. { 1, 1 },
    39. { 1, 0 }
    40. };
    41. int[][] res = matrixPower(base, n - 2);// 斐波那契base矩阵的n-2次幂,结果还是二维矩阵.
    42. return 1 * res[0][0] + 1 * res[1][0]; // |F(n),F(n-1)| = |F(2),F(1)| * |x,y|
    43. // |t,z|
    44. }
    45. // 求某个矩阵的p次幂
    46. public static int[][] matrixPower(int[][] m, int p) {
    47. int[][] res = new int[m.length][m[0].length];
    48. for (int i = 0; i < res.length; i++) {
    49. res[i][i] = 1; // 单位矩阵
    50. }
    51. // res = 矩阵中的1
    52. int[][] t = m;// 矩阵1次方
    53. for (; p != 0; p >>= 1) {
    54. if ((p & 1) != 0) { // 最末尾有1
    55. res = muliMatrix(res, t);
    56. }
    57. t = muliMatrix(t, t);
    58. }
    59. return res;
    60. }
    61. // 两个矩阵相乘之后的结果返回
    62. public static int[][] muliMatrix(int[][] m1, int[][] m2) {
    63. int[][] res = new int[m1.length][m2[0].length];
    64. for (int i = 0; i < m1.length; i++) {
    65. for (int j = 0; j < m2[0].length; j++) {
    66. for (int k = 0; k < m2.length; k++) {
    67. res[i][j] += m1[i][k] * m2[k][j];
    68. }
    69. }
    70. }
    71. return res;
    72. }

    题目2:
    母牛生小牛问题,求N年后牛的总数。

    1. /**
    2. * 第一年农场有1只成熟的母牛A,往后的每年:
    3. * 1)每一只成熟的母牛都会生一只母牛
    4. * 2)每一只新出生的母牛都在出生的第三年成熟
    5. * 3)每一只母牛永远不会死
    6. * 返回N年后牛的数量。
    7. */
    8. public static int c1(int n) {
    9. if (n < 1) {
    10. return 0;
    11. }
    12. if (n == 1 || n == 2 || n == 3) {
    13. return n;
    14. }
    15. return c1(n - 1) + c1(n - 3);
    16. }
    17. public static int c2(int n) {
    18. if (n < 1) {
    19. return 0;
    20. }
    21. if (n == 1 || n == 2 || n == 3) {
    22. return n;
    23. }
    24. int res = 3;
    25. int pre = 2;
    26. int prepre = 1;
    27. int tmp1 = 0;
    28. int tmp2 = 0;
    29. for (int i = 4; i <= n; i++) {
    30. tmp1 = res;
    31. tmp2 = pre;
    32. res = res + prepre;
    33. pre = tmp1;
    34. prepre = tmp2;
    35. }
    36. return res;
    37. }
    38. public static int c3(int n) {
    39. if (n < 1) {
    40. return 0;
    41. }
    42. if (n == 1 || n == 2 || n == 3) {
    43. return n;
    44. }
    45. // base系数矩阵
    46. int[][] base = {
    47. { 1, 1, 0 },
    48. { 0, 0, 1 },
    49. { 1, 0, 0 } };
    50. int[][] res = matrixPower(base, n - 3);
    51. return 3 * res[0][0] + 2 * res[1][0] + res[2][0];