2024/08/19 每日一题

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;
    }
}
posted @   Koonan-Edogawa  阅读(5)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示