LeetCode 552 学生出勤记录II
方法1:动态规划
class Solution {static int MOD = 1_000_000_007;static int MX = 1_000_01;static int[][][] dp = new int[MX][2][3];static { // 静态代码块dp[0][0][0] = 1; // 只有此时合法for (int i = 1; i < MX; i++) {dp[i][0][0] = add(dp[i - 1][0][0], dp[i - 1][0][1], dp[i - 1][0][2]);dp[i][0][1] = dp[i - 1][0][0];dp[i][0][2] = dp[i - 1][0][1];dp[i][1][0] = add(dp[i][0][0], dp[i - 1][1][0], dp[i - 1][1][1], dp[i - 1][1][2]);// dp[i][1][0] = dp[i - 1][0][0] + dp[i - 1][0][1] + dp[i - 1][0][2] + dp[i - 1][1][0] + dp[i - 1][1][1] + dp[i - 1][1][2];dp[i][1][1] = dp[i - 1][1][0];dp[i][1][2] = dp[i - 1][1][1];}}static int add(int... nums) {int res = nums[0];for (int i = 1; i < nums.length; i++) res = (res + nums[i]) % MOD;return res;}public int checkRecord(int n) {int ans = 0;for (int j = 0; j <= 1; j++) {for (int k = 0; k <= 2; k++) {ans = (ans + dp[n][j][k]) % MOD;}}return ans;}
}
方法2:动态规划 + 快速幂优化
class Solution {static int MOD = 1_000_000_007;static int length = 6;public int checkRecord(int n) {int[][] mat = { {1, 1, 1, 0, 0, 0},{1, 0, 0, 0, 0, 0},{0, 1, 0, 0, 0, 0},{1, 1, 1, 1, 1, 1},{0, 0, 0, 1, 0, 0},{0, 0, 0, 0, 1, 0} };return qpow(mat, n); // 第一列求和}static int qpow(int[][] mat, int n) {int[][] res = new int[length][length];for (int i = 0; i < length; i++) res[i][i] = 1;while (n > 0) {if ((n & 1) == 1)res = multiply(res, mat);mat = multiply(mat, mat);n >>= 1;}int ans = 0;for (int i = 0; i < length; i++) ans = (ans + res[i][0]) % MOD;return ans;}static int[][] multiply(int[][] arr1, int[][] arr2) {int[][] arr = new int[length][length];for (int i = 0; i < length; i++) {for (int j = 0; j < length; j++) {for (int k = 0; k < length; k++) {// 保证相乘不会越界arr[i][j] += mul(arr1[i][k], arr2[k][j]);arr[i][j] %= MOD; // 保证后续相加不越界}}}return arr;}static int mul(int num1, int num2) {int res = 0;while (num2 > 0) {if ((num2 & 1) == 1)res = (res + num1) % MOD;num1 = (num1 + num1) % MOD;num2 >>= 1;}return res;}
}