Fast Power of Matrix: PIPI's Math Problem IV

Fast Power of Matrix: PIPI's Math Problem IV

question:

insert image description here
insert image description here

Ideas:

  Finding the Fibonacci sequence is actually a DP problem. The state transition equation of DP has been given. The problem is to use the given state transition equation to perform linear recursion. The time complexity is O(n). However, the n of this question has reached the scale of 1e10, and it will definitely time out. So is there any way to optimize it? The answer is matrix fast exponentiation.
  What is fast power? Here is a portal: Mathematics topic: congruence theorem, gcd and lcm, median theorem, sieve method, fast power, etc.
  So what is matrix fast power? Matrix fast exponentiation is actually to express the state transition equation of DP in the form of matrix multiplication, and then reduce the time complexity through the method of fast exponentiation. For example, using matrix fast power, the time complexity of this question O(n) will be reduced to O(logn).
  Let's first look at DP[2] = DP[1] + DP[0], we can construct such a matrix multiplication To find DP[2]:
insert image description here
  Then how to find DP[3], and then multiply it by a matrix we constructed:
insert image description here
  and so on, we can find the law as follows:
insert image description here
  So, for finding DP[n], we can Instead of using linear recursion, it is found by the method of matrix power. According to the fast power algorithm, it only needs to do logn matrix multiplications to calculate the n-1 power of the second matrix. And this is a 2*2 matrix, and the complexity of each matrix multiplication is a constant. Therefore, using matrix fast power can optimize the time complexity from O(n) to O(logn).

  Generally, matrix fast powers are associated with DP. When DP state transition equations are found, but the scale is large, you can consider constructing matrix fast powers for optimization.

code:

import java.util.*;

public class Main {
    
    
    static long[][] startMatrix = new long[2][2];
    static long[][] mulMatrix = new long[2][2];
    static final long MOD_NUM = (long) (1e9 + 7);
    public static void main(String[] args) {
    
    
        startMatrix[0][0] = 1;
        startMatrix[0][1] = 1;
        mulMatrix[0][0] = 1;
        mulMatrix[0][1] = 1;
        mulMatrix[1][0] = 1;
        long k;
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNextLong()) {
    
    
            k = scanner.nextLong();
            System.out.println(fastMatrixPow(startMatrix, k - 1)[0][0] % MOD_NUM);
        }

    }

    static long[][] fastMatrixPow(long[][] matrix, long powNum) {
    
    
        long[][] baseMatrix = mulMatrix;
        while (powNum != 0) {
    
    
            if ((powNum & 1) == 1) {
    
    
                matrix = mulMatrix(matrix, baseMatrix);
            }
            baseMatrix = mulMatrix(baseMatrix, baseMatrix);
            powNum >>= 1;
        }
        return matrix;
    }

    static long[][] mulMatrix(long[][] matrix1, long[][] matrix2) {
    
    
        long[][] ans = new long[2][2];
        ans[0][0] = (matrix1[0][0] * matrix2[0][0] % MOD_NUM)
                    + (matrix1[0][1] * matrix2[1][0] % MOD_NUM);
        ans[0][1] = (matrix1[0][0] * matrix2[0][1] % MOD_NUM)
                + (matrix1[0][1] * matrix2[1][1] % MOD_NUM);
        ans[1][0] = (matrix1[1][0] * matrix2[0][0] % MOD_NUM)
                + (matrix1[1][1] * matrix2[1][0] % MOD_NUM);
        ans[1][1] = (matrix1[1][0] * matrix2[0][1] % MOD_NUM)
                + (matrix1[1][1] * matrix2[1][1] % MOD_NUM);
        return ans;
    }
}

Guess you like

Origin blog.csdn.net/qq_44709990/article/details/123394820