【力扣周赛】第 362 场周赛(⭐差分匹配状态压缩DP矩阵快速幂优化DPKMP)

news2024/11/20 20:43:46

文章目录

  • 竞赛链接
  • Q1:2848. 与车相交的点
    • 解法1——排序后枚举
    • 解法2——差分数组⭐
    • 差分数组相关题目列表📕
      • 1094. 拼车
      • 1109. 航班预订统计
      • 2381. 字母移位 II
      • 2406. 将区间分为最少组数
        • 解法1——排序贪心+优先队列
        • 解法2——差分数组
      • 2772. 使数组中的所有元素都等于零
      • 2528. 最大化城市的最小供电站数目(⭐差分数组 + 二分查找答案)
        • 最大化最小化相关题目列表📕
          • 2439. 最小化数组中的最大值
            • 解法1——二分答案
            • 解法2——分类讨论O(n)
          • 2513. 最小化两个数组中的最大值(二分答案+lcm+容斥原理)🐂好题!
          • 2517. 礼盒的最大甜蜜度(二分答案)
  • Q2:2849. 判断能否在给定时间到达单元格(脑筋急转弯、贪心)
  • Q3:2850. 将石头分散到网格图的最少移动次数⭐⭐⭐(全排列和状态压缩)
    • 解法1——枚举全排列
    • 解法2——最小费用最大流 (TODO)
    • 解法3——状压DP
    • 涉及到「匹配」的题目列表📕
      • 1947. 最大兼容性评分和
        • 解法1——枚举全排列
        • 解法2——状态压缩DP
      • 1349. 参加考试的最大学生数🚹(状态压缩DP)
      • LCP 04. 覆盖🚹(TODO 二分图匹配 & 状态压缩DP)
        • 解法1——二分图匹配
        • 解法2——状态压缩DP
      • 1879. 两个数组最小的异或值之和(状态压缩DP)
      • 2172. 数组的最大与和(状态压缩DP)
  • Q4:2851. 字符串转换⭐
    • 解法1——KMP + 矩阵快速幂优化 DP 🐂
    • 解法2——找规律,无需矩阵快速幂(TODO)
    • [矩阵快速幂] 题目列表📕
      • 70. 爬楼梯
        • 解法1——线性DP
        • 解法2——矩阵快速幂
      • 509. 斐波那契数
      • 1137. 第 N 个泰波那契数
      • 1220. 统计元音字母序列的数目
        • 解法1——线性DP
        • 解法2——矩阵快速幂优化DP
      • 552. 学生出勤记录 II(🚹递归公式 & 矩阵快速幂优化🐂)
        • 解法1——动态规划
        • 解法2——矩阵快速幂优化DP(TODO)
      • 790. 多米诺和托米诺平铺⭐(🚹想出递推公式)
        • 解法1——动态规划1 分最后一列的状态
        • 解法2——动态规划2 列出式子找通项公式(TODO 还没想明白)
        • 解法3——矩阵快速幂优化DP
  • 成绩记录

竞赛链接

https://leetcode.cn/contest/weekly-contest-362/

Q1:2848. 与车相交的点

https://leetcode.cn/problems/points-that-intersect-with-cars/description/

在这里插入图片描述

提示:
1 <= nums.length <= 100
nums[i].length == 2
1 <= starti <= endi <= 100

解法1——排序后枚举

排序之后按顺序枚举,每次比较和上个区间结束位置之间的关系。

class Solution {
    public int numberOfPoints(List<List<Integer>> nums) {
        int ans = 0, last = -1;
        Collections.sort(nums, (x, y) -> x.get(0) - y.get(0));
        for (List<Integer> x: nums) {
            ans += Math.max(0, x.get(1) - Math.max(last + 1, x.get(0)) + 1);
            last = Math.max(last, x.get(1));
        }
        return ans;
    }
}

解法2——差分数组⭐

https://leetcode.cn/problems/points-that-intersect-with-cars/solutions/2435384/chai-fen-shu-zu-xian-xing-zuo-fa-by-endl-3xpm/

关于差分可见:【算法基础】1.5 前缀和与差分

class Solution {
    public int numberOfPoints(List<List<Integer>> nums) {
        int[] diff = new int[102];
        // 利用差分将区间内所有位置 +1
        for (List<Integer> p: nums) {
            diff[p.get(0)]++;
            diff[p.get(1) + 1]--;
        }
        int ans = 0, s = 0;
        // 检查各个位置  如果>0则ans++
        for (int d: diff) {
            s += d;
            if (s > 0) ans++;
        }
        return ans;
    }
}

差分数组相关题目列表📕

题目列表来源:分享|【算法小课堂】差分数组(Python/Java/C++/Go/JS)

1094. 拼车

https://leetcode.cn/problems/car-pooling/
在这里插入图片描述
提示:

1 <= trips.length <= 1000
trips[i].length == 3
1 <= numPassengersi <= 100
0 <= fromi < toi <= 1000
1 <= capacity <= 10^5

用差分 表示 from 到 to 的范围内增加了多少人,然后再还原。

class Solution {
    public boolean carPooling(int[][] trips, int capacity) {
        int[] diff = new int[1002];
        // 构造差分数组
        for (int[] t: trips) {
            diff[t[1]] += t[0];
            diff[t[2]] -= t[0];
        }
        // 差分数组的还原
        for (int i = 0; i <= 1000; ++i) {
            if (diff[i] > capacity) return false;
            diff[i + 1] += diff[i];
        }
        return true;
    }
}

1109. 航班预订统计

https://leetcode.cn/problems/corporate-flight-bookings/

在这里插入图片描述
提示
1 <= n <= 2 * 10^4
1 <= bookings.length <= 2 * 10^4
bookings[i].length == 3
1 <= firsti <= lasti <= n
1 <= seatsi <= 10^4

class Solution {
    public int[] corpFlightBookings(int[][] bookings, int n) {
        int[] ans = new int[n], diff = new int[n + 1];
        for (int[] booking: bookings) {
            diff[booking[0] - 1] += booking[2];
            diff[booking[1]] -= booking[2];
        }
        for (int i = 0; i < n; ++i) {
            ans[i] = diff[i];
            diff[i + 1] += diff[i];
        }
        return ans;
    }
}

2381. 字母移位 II

https://leetcode.cn/problems/shifting-letters-ii/

在这里插入图片描述

提示
1 <= s.length, shifts.length <= 5 * 10^4
shifts[i].length == 3
0 <= starti <= endi < s.length
0 <= directioni <= 1
s 只包含小写英文字母。

class Solution {
    public String shiftingLetters(String s, int[][] shifts) {
        int n = s.length();
        // 构造差分数组
        int[] diff = new int[n + 1];
        for (int[] shift: shifts) {
            int t = shift[2] == 1? 1: -1;
            diff[shift[0]] += t;
            diff[shift[1] + 1] -= t;
        }
        // 差分数组和答案的还原
        char[] ans = new char[n];
        for (int i = 0; i < n; ++i) {
            ans[i] = op(s.charAt(i), diff[i]);
            diff[i + 1] += diff[i];
        }
        return String.valueOf(ans);
    }

    // 对字符 a 移动 x
    public char op(char a, int x) {
        return (char)(((a - 'a' + x % 26) + 26) % 26 + 'a');
    }
}

2406. 将区间分为最少组数

https://leetcode.cn/problems/divide-intervals-into-minimum-number-of-groups/
在这里插入图片描述
提示:

1 <= intervals.length <= 1^05
intervals[i].length == 2
1 <= lefti <= righti <= 10^6

解法1——排序贪心+优先队列

按照区间的开始位置从小到大排序。
想象每个组合就是一个列表,我们使用有限队列维护这些列表的末尾位置。
这样每次枚举到一个新的区间,检查是否可以放入已有列表中,如果可以,就将一个已有列表的末尾位置换成当前区间的结尾位置。

class Solution {
    public int minGroups(int[][] intervals) {
        Arrays.sort(intervals, (x, y) -> x[0] - y[0]);
        PriorityQueue<Integer> pq = new PriorityQueue<>((x, y) -> x - y);
        for (int[] interval: intervals) {
            if (!pq.isEmpty() && pq.peek() < interval[0]) pq.poll();
            pq.offer(interval[1]);
        }
        return pq.size();
    }
}

解法2——差分数组

差分还原中出现的最大值就是答案。

class Solution {
    public int minGroups(int[][] intervals) {
        TreeMap<Integer, Integer> diff = new TreeMap<>();
        int ans = 0, sum = 0;
        // 计算差分
        for (int[] interval: intervals) {
            diff.merge(interval[0], 1, Integer::sum);
            diff.merge(interval[1] + 1, -1, Integer::sum);
        }
        // 还原差分
        for (Map.Entry<Integer, Integer> entry: diff.entrySet()) {
            sum += entry.getValue();
            ans = Math.max(ans, sum);
        }
        return ans;
    }
}

2772. 使数组中的所有元素都等于零

https://leetcode.cn/problems/apply-operations-to-make-all-array-elements-equal-to-zero/

在这里插入图片描述
提示:

1 <= k <= nums.length <= 10^5
0 <= nums[i] <= 10^6

有点差分的思想,又不太一样。

贪心地从前往后枚举每一个位置,只要 > 0 就减,< 0 就返回 false。

class Solution {
    public boolean checkArray(int[] nums, int k) {
        int n = nums.length, diff = 0, ans = 0;
        int[] x = new int[n];
        for (int i = 0; i < n; ++i) {
            if (i >= k) diff -= x[i - k];
            if (nums[i] > diff) {
                if (n - i < k) return false;
                ans += nums[i] - diff;      // 更新答案
                x[i] = nums[i] - diff;      // 记录这个位置减去了多少
                diff = nums[i];             // 更新diff
            } else if (nums[i] < diff) return false;
        }
        return true;
    }
}

2528. 最大化城市的最小供电站数目(⭐差分数组 + 二分查找答案)

https://leetcode.cn/problems/maximize-the-minimum-powered-city/
在这里插入图片描述
提示:
n == stations.length
1 <= n <= 10^5
0 <= stations[i] <= 10^5
0 <= r <= n - 1
0 <= k <= 10^9

看到「最大化最小值」或者「最小化最大值」就要想到二分答案,这是一个固定的套路。

class Solution {
    public long maxPower(int[] stations, int r, int k) {
        int n = stations.length;
        long mn = Long.MAX_VALUE;
        // 计算差分数组
        long[] cnt = new long[n + 1];
        for (int i = 0; i < n; ++i) {
            cnt[Math.max(0, i - r)] += stations[i];
            cnt[Math.min(n, i + r + 1)] -= stations[i];
        }
        // 差分数组的还原
        for (int i = 0; i < n; ++i) {
            cnt[i + 1] += cnt[i];
            mn = Math.min(mn, cnt[i]);
        }
        // 二分查找答案
        long left = mn, right = mn + k;
        while (left < right) {
            long mid = left + right + 1 >> 1;
            if (!check(cnt, mid, r, k)) right = mid - 1;
            else left = mid;
        }
        return left;
    }

    // check过程类似 T2772. 使数组中的所有元素都等于零
    public boolean check(long[] cnt, long x, int r, int k) {
        long diff = 0;
        int n = cnt.length - 1;
        long[] d = new long[n];
        for (int i = 0; i < n; ++i) {
            if (i >= 2 * r + 1) diff -= d[i - 2 * r - 1];
            if (cnt[i] + diff < x) {
                d[i] = x - cnt[i] - diff;
                k -= d[i];
                diff = x - cnt[i];
            }
        }
        return k >= 0;
    }
}

最大化最小化相关题目列表📕

题目列表来源:https://leetcode.cn/problems/maximize-the-minimum-powered-city/solutions/2050272/er-fen-da-an-qian-zhui-he-chai-fen-shu-z-jnyv/
在这里插入图片描述

2439. 最小化数组中的最大值

https://leetcode.cn/problems/minimize-maximum-of-array/
在这里插入图片描述

提示:
n == nums.length
2 <= n <= 10^5
0 <= nums[i] <= 10^9

解法1——二分答案
class Solution {
    public int minimizeArrayValue(int[] nums) {
        int l = Integer.MAX_VALUE, r = Integer.MIN_VALUE;
        for (int x: nums) {
            l = Math.min(l, x);
            r = Math.max(r, x);
        }
        while (l < r) {
            int mid = l + r >> 1;
            if (check(mid, nums)) r = mid;
            else l = mid + 1;
        }
        return l;
    }

    public boolean check(int k, int[] nums) {
        if (nums[0] > k) return false;
        long d = k - nums[0];           // 使用long防止溢出
        for (int i = 1; i < nums.length; ++i) {
            if (nums[i] <= k) d += k - nums[i];
            else {
                d -= nums[i] - k;
                if (d < 0) return false;
            }
        }
        return true;
    }
}
解法2——分类讨论O(n)

首先最大值的最小值是 nums[0]。
对于 nums[1],当其 < nums[0] 时,答案还是 nums[0];当其 > nums[0] 时,则答案是两者的平均向上取整。

class Solution {
    public int minimizeArrayValue(int[] nums) {
        long mx = 0, sum = 0;
        for (int i = 0; i < nums.length; ++i) {
            sum += nums[i];
            // (sum + i) / (i + 1) 是因为要向上取整
            mx = Math.max(mx, (sum + i) / (i + 1));     
        }
        return (int)mx;
    }
}
2513. 最小化两个数组中的最大值(二分答案+lcm+容斥原理)🐂好题!

https://leetcode.cn/problems/minimize-the-maximum-of-two-arrays/
在这里插入图片描述

提示:
2 <= divisor1, divisor2 <= 10^5
1 <= uniqueCnt1, uniqueCnt2 < 10^9
2 <= uniqueCnt1 + uniqueCnt2 <= 10^9

二分答案。

class Solution {
    public int minimizeSet(int divisor1, int divisor2, int uniqueCnt1, int uniqueCnt2) {
        long l = 0, r = (long)Integer.MAX_VALUE;
        while (l < r) {
            long mid = l + r >> 1;
            // 两个数组不能选择的数字数量
            long x = mid / divisor1, y = mid / divisor2, z = mid / lcm(divisor1, divisor2);
            long sum = uniqueCnt1 + uniqueCnt2 + z;         // 至少需要的数字数量
            // arr1不能使用的,看arr2能不能使用;反之同理
            sum += Math.max(0, x - z - uniqueCnt2) + Math.max(0, y - z - uniqueCnt1);
            if (sum <= mid) r = mid;
            else l = mid + 1;
        }
        return (int)l;
    }

    // 最小公倍数
    public long lcm(long x, long y) {
        return x / gcd(x, y) * y;
    }

    // 最大公因数
    public long gcd(long x, long y) {
        return y == 0? x: gcd(y, x % y);
    }
}
2517. 礼盒的最大甜蜜度(二分答案)

https://leetcode.cn/problems/maximum-tastiness-of-candy-basket/
在这里插入图片描述
提示:
2 <= k <= price.length <= 10^5
1 <= price[i] <= 10^9

class Solution {
    public int maximumTastiness(int[] price, int k) {
        Arrays.sort(price);
        int n = price.length, l = 0, r = price[n - 1] - price[0];
        while (l < r) {
            int mid = l + r + 1 >> 1;
            int s = 1, last = price[0];
            for (int i = 1; i < n && s < k; ++i) {
                if (price[i] - last >= mid) {
                    s++;
                    last = price[i];
                }
            }
            if (s < k) r = mid - 1;
            else l = mid;
        }
        return l;
    }
}

Q2:2849. 判断能否在给定时间到达单元格(脑筋急转弯、贪心)

https://leetcode.cn/problems/determine-if-a-cell-is-reachable-at-a-given-time/

在这里插入图片描述

提示:
1 <= sx, sy, fx, fy <= 109
0 <= t <= 10^9

斜着走,一步顶两步——相当于可以同时横着走和竖着走。 那么只要满足垂直和水平方向中最长的那个距离就好了。

注意有个特例是:只走一步时,如果起点和终点相同就不可以了。

class Solution {
    public boolean isReachableAtTime(int sx, int sy, int fx, int fy, int t) {
        if (sx == fx && sy == fy && t == 1) return false;		// 特例
        return t >= Math.max(Math.abs(sx - fx), Math.abs(sy - fy));
    }
}

Q3:2850. 将石头分散到网格图的最少移动次数⭐⭐⭐(全排列和状态压缩)

https://leetcode.cn/problems/minimum-moves-to-spread-stones-over-grid/
在这里插入图片描述

提示:

grid.length == grid[i].length == 3
0 <= grid[i][j] <= 9
grid 中元素之和为 9

解法1——枚举全排列

https://leetcode.cn/problems/minimum-moves-to-spread-stones-over-grid/solutions/2435313/tong-yong-zuo-fa-zui-xiao-fei-yong-zui-d-iuw8/

将起始点和终点分别放入两个列表,做全排列匹配。
枚举所有全排列,比较各种情况下的移动次数,得出最小移动次数。

class Solution {
    int ans = Integer.MAX_VALUE, sum = 0;
    boolean[] st = new boolean[9];

    public int minimumMoves(int[][] grid) {
        // 将起始点和终点放入列表
        List<int[]> src = new ArrayList<>(), dst = new ArrayList<>();
        for (int i = 0; i < 3; ++i) {
            for (int j = 0; j < 3; ++j) {
                while (grid[i][j] > 1) {
                    src.add(new int[]{i, j});
                    grid[i][j]--;
                }
                if (grid[i][j] == 0) dst.add(new int[]{i, j});
            }
        }
        // dfs全排列
        dfs(0, src, dst);
        return ans;
    }

    public void dfs(int i, List<int[]> src, List<int[]> dst) {
        if (i == src.size()) {
            ans = Math.min(ans, sum);
            return;
        }
        for (int j = 0; j < dst.size(); ++j) {
            if (!st[j]) {
                int[] s = src.get(i), d = dst.get(j);
                sum += Math.abs(s[0] - d[0]) + Math.abs(s[1] - d[1]);
                st[j] = true;
                dfs(i + 1, src, dst);
                sum -= Math.abs(s[0] - d[0]) + Math.abs(s[1] - d[1]);
                st[j] = false;
            }
        }
    }
}

解法2——最小费用最大流 (TODO)

https://leetcode.cn/problems/minimum-moves-to-spread-stones-over-grid/solutions/2435313/tong-yong-zuo-fa-zui-xiao-fei-yong-zui-d-iuw8/

在这里插入代码片

解法3——状压DP

https://leetcode.cn/problems/minimum-moves-to-spread-stones-over-grid/solutions/2435319/zhuang-ya-dp-by-tsreaper-jiw0/

状态压缩DP相比全排列速度更快(48ms vs 3ms)

class Solution {
    public int minimumMoves(int[][] grid) {
        // 起始点和目的点放入两个列表
        List<int[]> L = new ArrayList<>(), R = new ArrayList<>();
        for (int i = 0; i < 3; ++i) {
            for (int j = 0; j < 3; ++j) {
                if (grid[i][j] == 0) R.add(new int[]{i, j});
                else {
                    for (; grid[i][j] > 1; grid[i][j]--) {
                        L.add(new int[]{i, j});
                    }
                }
            }
        }

        // 状态压缩DP
        int n = L.size();
        int[] dp = new int[1 << n];
        Arrays.fill(dp, Integer.MAX_VALUE);
        dp[0] = 0;
        for (int i = 1; i < (1<<n); ++i) {
            // 计算 i 中有几个二进制等于 1——为了确定当前目的点是哪个
            int cnt = 0;
            for (int j = 0; j < n; ++j) {
                cnt += i >> j & 1;
            }
            // 状态转移
            for (int j = 0; j < n; ++j) {   // 枚举所有目标点
                if ((i >> j & 1) == 1) {    // 检查是否为1,即是否可以从前面转移过来
                    dp[i] = Math.min(dp[i], dp[i ^ (1 << j)] + cost(R.get(cnt - 1), L.get(j)));
                }
            }
        }
        return dp[(1<<n) - 1];
    }

    public int cost(int[] a, int[] b) {
        return Math.abs(a[0] - b[0]) + Math.abs(a[1] - b[1]);
    }
}

涉及到「匹配」的题目列表📕

题单来源:https://leetcode.cn/problems/minimum-moves-to-spread-stones-over-grid/solutions/2435313/tong-yong-zuo-fa-zui-xiao-fei-yong-zui-d-iuw8/

1947. 最大兼容性评分和

https://leetcode.cn/problems/maximum-compatibility-score-sum/

在这里插入图片描述
提示:
m == students.length == mentors.length
n == students[i].length == mentors[j].length
1 <= m, n <= 8
students[i][k] 为 0 或 1
mentors[j][k] 为 0 或 1

解法1——枚举全排列

数据范围很小,可以枚举出所有学生和老师之间匹配的方案。

class Solution {
    int ans = 0;
    boolean[] st = new boolean[8];

    public int maxCompatibilitySum(int[][] students, int[][] mentors) {
        // 全排列
        dfs(students, mentors, 0, 0);
        return ans;
    }

    public void dfs(int[][] students, int[][] mentors, int i, int sum) {
        if (i == students.length) {
            ans = Math.max(ans, sum);
            return;
        }
        for (int j = 0; j < mentors.length; ++j) {
            if (st[j]) continue;
            st[j] = true;
            dfs(students, mentors, i + 1, sum + cp(students[i], mentors[j]));
            st[j] = false;
        }
    }

    // 计算某个学生和某个老师的兼容性评分
    public int cp(int[] s, int[] t) {
        int res = 0;
        for (int i = 0; i < s.length; ++i) {
            if (s[i] == t[i]) res++;
        }
        return res;
    }
}

解法2——状态压缩DP

class Solution {
    public int maxCompatibilitySum(int[][] students, int[][] mentors) {
        int n = students.length;
        int[][] dp = new int[n + 1][1<<n];  // dp[i][j]表示匹配完i个老师,和集合j的学生的最大匹配和
        // 枚举每个状态
        for (int i = 1; i < (1<<n); ++i) {
            int idx = Integer.bitCount(i);  // 计算该匹配哪个老师了
            // 枚举每个学生
            for (int j = 0; j < n; ++j) {
                if ((i >> j & 1) == 1) {    // 如果可以转移
                    dp[idx][i] = Math.max(dp[idx][i], dp[idx - 1][i ^ (1<<j)] + cp(students[j], mentors[idx - 1]));
                }
            }
        }
        return dp[n][(1<<n) - 1];
    }

    // 计算某个学生和某个老师的兼容性评分
    public int cp(int[] s, int[] t) {
        int res = 0;
        for (int i = 0; i < s.length; ++i) {
            if (s[i] == t[i]) res++;
        }
        return res;
    }
}

1349. 参加考试的最大学生数🚹(状态压缩DP)

https://leetcode.cn/problems/maximum-students-taking-exam/
在这里插入图片描述

提示:
seats 只包含字符 '.' 和'#'
m == seats.length
n == seats[i].length
1 <= m <= 8
1 <= n <= 8

将每一行选择的位置用一个int变量表示。

枚举每一行,再枚举该行的状态,然后枚举上一行的状态,检测是否合理且可以转移过来。
最后的答案就是最后一行各个状态的最大值。


这里的合理包括:

  1. 该行本身要合理,—— 都要坐在正常的椅子上;同一行的两个学生不能挨边坐。
  2. 每一行和上一行之间不能有冲突——如果上一行的某一列已经坐人了,那么该行该列的左右两侧就不能坐人了。
class Solution {
    public int maxStudents(char[][] seats) {
        int m = seats.length, n = seats[0].length;
        int[] states = new int[m];
        for (int i = 0; i < m; ++i) {
            states[i] = getMask(seats[i]);
        }
        // 一共m行,每行1<<n种状态
        int[][] dp = new int[m + 1][1 << n];
        for (int i = 0; i < 1<<n; ++i) {
            // 判断 i 是不是 states[0] 的子集 && 自己不冲突
            if (check(states[0], i) && op(i)) {
                dp[0][i] = Integer.bitCount(i);
            }
        }
        // 枚举每一行
        for (int i = 1; i < m; ++i) {
            // 枚举这一行的每个状态
            for (int j = 0; j < 1<<n; ++j) {
                if (!check(states[i], j)) continue;     // 如果这个状态不合理,就跳过
                // 枚举上一行的每个状态
                for (int k = 0; k < 1<<n; ++k) {
                    if (!check(states[i - 1], k)) continue; // 如果这个状态不合理,就跳过
                    if (!confilt(k, j)) {               // 如果这个状态和上一行不冲突
                        dp[i][j] = Math.max(dp[i][j], dp[i - 1][k] + Integer.bitCount(j));
                    }
                }
                
            }
            System.out.println();
        }
        return Arrays.stream(dp[m - 1]).max().getAsInt();
    }

    // 将一行的状态用一个int表示
    public int getMask(char[] state) {
        int res = 0;
        for (int i = 0; i < state.length; ++i) {
            if (state[i] == '.') res |= 1 << i;
        }
        return res;
    }

    // 检查状态x是否是状态state的子集,即是否可选 && 这个状态x本身合法
    public boolean check(int state, int x) {
        if ((state | x) != state) return false;      // 需要x是state的子集
        return op(x);       
    }

    // 检查x是否和y作为上一行冲突
    public boolean confilt(int x, int y) {
        for (int i = 0; i < 10; ++i) {
            if ((x >> i & 1) == 1) {    // 如果x这个位置有了
                // 那么y的相差一列的位置就不能有了
                if ((y >> i + 1 & 1) == 1 || (y >> i - 1 & 1) == 1) {
                    return true;
                }
            }
        }
        return false;
    }

    // 检查这一行的状态本身是否合理,即检查是否有两个学生坐在挨边的位置上
    public boolean op(int x) {
        for (int i = 0; i < 9; ++i) {
            if ((x >> i & 1) == 1 && (x >> i + 1 & 1) == 1) return false;
        }
        return true;
    }
}

LCP 04. 覆盖🚹(TODO 二分图匹配 & 状态压缩DP)

https://leetcode.cn/problems/broken-board-dominoes/

在这里插入图片描述

限制:
1 <= n <= 8
1 <= m <= 8
0 <= b <= n * m

解法1——二分图匹配

在这里插入代码片

解法2——状态压缩DP

在这里插入代码片

1879. 两个数组最小的异或值之和(状态压缩DP)

https://leetcode.cn/problems/minimum-xor-sum-of-two-arrays/

在这里插入图片描述
提示:
n == nums1.length
n == nums2.length
1 <= n <= 14
0 <= nums1[i], nums2[i] <= 10^7

class Solution {
    public int minimumXORSum(int[] nums1, int[] nums2) {
        int n = nums1.length;
        int[][] dp = new int[n + 1][1 << n];
        for (int i = 0; i <= n; ++i) Arrays.fill(dp[i], Integer.MAX_VALUE / 2);
        dp[0][0] = 0;
        // 枚举nums1的每个状态
        for (int i = 1; i < 1<<n; ++i) {
            int cnt = Integer.bitCount(i);
            // 枚举每个位置
            for (int j = 0; j < n; ++j) {
                if ((i >> j & 1) == 1) {
                    dp[cnt][i] = Math.min(dp[cnt][i], dp[cnt - 1][i ^ (1<<j)] + (nums1[j] ^ nums2[cnt - 1]));
                }
            }
        }
        return dp[n][(1<<n) - 1];
    }
}

2172. 数组的最大与和(状态压缩DP)

https://leetcode.cn/problems/maximum-and-sum-of-array/
在这里插入图片描述

提示:
n == nums.length
1 <= numSlots <= 9
1 <= n <= 2 * numSlots
1 <= nums[i] <= 15

每个篮子可以放最多 2 个数字,那么可以分成有 2 组一模一样的篮子处理。

注意——要将篮子的使用集合作为状态。

class Solution {
    public int maximumANDSum(int[] nums, int numSlots) {
        int n = nums.length, m = 2 * numSlots, ans = 0;
        int[] dp = new int[1<<m];   // m个篮子的状态
        // 枚举每个篮子被选择情况
        for (int i = 1; i < 1<<m; ++i) {
            // 计算该放入那个num了
            int cnt = Integer.bitCount(i);
            if (cnt > n) continue;
            // 枚举每个被选择的篮子
            for (int j = 0; j < m; ++j) {
                if ((i >> j & 1) == 1) {
                    dp[i] = Math.max(dp[i], dp[i ^ (1<<j)] + (nums[cnt - 1] & (j % numSlots + 1)));
                }
            }
            ans = Math.max(ans, dp[i]);
        }
        return ans;
    }
}

Q4:2851. 字符串转换⭐

https://leetcode.cn/problems/string-transformation/
在这里插入图片描述

提示:
2 <= s.length <= 5 * 10^5
1 <= k <= 10^15
s.length == t.length
s 和 t 都只包含小写英文字母。

解法1——KMP + 矩阵快速幂优化 DP 🐂

https://leetcode.cn/problems/string-transformation/solutions/2435348/kmp-ju-zhen-kuai-su-mi-you-hua-dp-by-end-vypf/

计算有多少个 s 的循环同构字符串等于 t,记作 c。这可以用 KMP 等字符串匹配算法解决,即寻找 t 在 s+s(去掉最后一个字符)中的出现次数。(用KMP计算出 s + s 中有几个 t
关于 KMP 可见:我一定要 学会KMP字符串匹配

下面使用动态规划来解决该问题——
定义 f[i][0] 表示 i 次操作后等于 t 的方案数,f[i][1] 表示 i 次操作后不等于 t 的方案数。
在这里插入图片描述
发现 DP 递推式可以写成矩阵乘法形式,因此可以使用矩阵快速幂来优化。(所谓矩阵快速幂,和普通快速幂的思想是一样的。)
在这里插入图片描述
快速幂可以完成从 O ( n ) O(n) O(n) O ( log ⁡ n ) O(\log{n}) O(logn) 的优化。

Q:为什么必须要使用矩阵快速幂?
A:因为 k 的数据范围很大。( log ⁡ n \log{n} logn 对应的数据范围是 1 0 18 10^{18} 1018

class Solution {
    final long MOD = (long)1e9 + 7;

    public int numberOfWays(String s, String t, long k) {
        int n = s.length();
        // kmp 求出 s+s(去掉最后一个字符) 中有几个 t
        int c = kmpSearch(s + s.substring(0, n - 1), t);
        // 递推矩阵
        long[][] m = {
            {c - 1, c},
            {n - c, n - 1 - c},
        };
        m = pow(m, k);      // 矩阵快速幂求结果
        // 根据 s==t? 判断初始状态 对应的答案
        return s.equals(t)? (int) m[0][0]: (int) m[0][1];
    }

    // kmp 返回 s 中有多少个 t
    public int kmpSearch(String s, String t) {
        int[] next = getNext(s.toCharArray());
        int c = 0;
        for (int i = 0, j = -1; i < s.length(); ++i) {
            while (j != -1 && s.charAt(i) != t.charAt(j + 1)) j = next[j];
            if (s.charAt(i) == t.charAt(j + 1)) j++;
            if (j == t.length() - 1) {
                c++;
                j = next[j];    // 匹配成功之后,记得要更新 j = next[j]
            }
        }
        return c;
    }

    // 求 next 数组
    public int[] getNext(char[] s) {
        int n = s.length;
        int[] next = new int[n];
        next[0] = -1;
        for (int i = 1, j = -1; i < n; ++i) {
            while (j != -1 && s[i] != s[j + 1]) j = next[j];
            if (s[i] == s[j + 1]) j++;
            next[i] = j;
        }
        return next;
    }

    // 矩阵快速幂
    public long[][] pow(long[][] a, long n) {
        long[][] res = {{1, 0}, {0, 1}};
        for (; n > 0; n /= 2) {
            if (n % 2 == 1) {
                res = multiply(res, a);
            }
            a = multiply(a, a);
        }
        return res;
    }

    // 矩阵乘法
    public long[][] multiply(long[][] a, long[][] b) {
        long[][] c = new long[2][2];
        for (int i = 0; i < 2; ++i) {
            for (int j = 0; j < 2; ++j) {
                c[i][j] = (a[i][0] * b[0][j] + a[i][1] * b[1][j]) % MOD;
            }
        }
        return c;
    }
}

解法2——找规律,无需矩阵快速幂(TODO)

https://leetcode.cn/problems/string-transformation/solutions/2435714/cjavapython-bu-xu-yao-ju-zhen-kuai-su-mi-cukc/

在这里插入代码片

[矩阵快速幂] 题目列表📕

题目列表来源:https://leetcode.cn/problems/string-transformation/solutions/2435348/kmp-ju-zhen-kuai-su-mi-you-hua-dp-by-end-vypf/

70. 爬楼梯

https://leetcode.cn/problems/climbing-stairs/
在这里插入图片描述

提示:
1 <= n <= 45

解法1——线性DP

class Solution {
    public int climbStairs(int n) {
        if (n <= 1) return n;
        int[] dp = new int[n];
        dp[0] = 1;
        dp[1] = 2;
        for (int i = 2; i < n; ++i) {
            dp[i] = dp[i - 1] + dp[i - 2];
        }
        return dp[n - 1];
    }
}

解法2——矩阵快速幂

根据递推公式,可以得出矩阵快速幂的矩阵是什么。

class Solution {
    public int climbStairs(int n) {
        if (n <= 2) return n;
        // m是根据递推公式来的
        int[][] m = {
            {1, 1},
            {1, 0}
        };
        return pow(m, n - 2)[0][0];
    }

    public int[][] pow(int[][] m, int k) {
        // dp[0] = 1,dp[1] = 2
        int[][] res = {
            {2, 0},
            {1, 0}
        };
        for (; k != 0; k /= 2) {
            if (k % 2 == 1) res = mul(m, res);
            m = mul(m, m);
        }
        return res;
    }

    public int[][] mul(int[][] x, int[][] y) {
        int[][] res = new int[2][2];
        for (int i = 0; i < 2; ++i) {
            for (int j = 0; j < 2; ++j) {
                res[i][j] = x[i][0] * y[0][j] + x[i][1] * y[1][j];
            }
        }
        return res;
    }
}

也可以更简洁一些,从 dp[0] 开始写,代码如下:

class Solution {
    public int climbStairs(int n) {
        // m是根据递推公式来的
        int[][] m = {
            {1, 1},
            {1, 0}
        };
        return pow(m, n)[0][0];
    }

    public int[][] pow(int[][] m, int k) {
        // dp[0] = 1
        int[][] res = {
            {1, 0},
            {0, 0}
        };
        for (; k != 0; k /= 2) {
            if (k % 2 == 1) res = mul(m, res);
            m = mul(m, m);
        }
        return res;
    }

    public int[][] mul(int[][] x, int[][] y) {
        int[][] res = new int[2][2];
        for (int i = 0; i < 2; ++i) {
            for (int j = 0; j < 2; ++j) {
                res[i][j] = x[i][0] * y[0][j] + x[i][1] * y[1][j];
            }
        }
        return res;
    }
}

509. 斐波那契数

https://leetcode.cn/problems/fibonacci-number/
在这里插入图片描述
提示:
0 <= n <= 30

跟上一题差不多,注意初始值变了。

class Solution {
    public int fib(int n) {
        if (n == 0) return n;
        // m是根据递推公式来的
        int[][] m = {
            {1, 1},
            {1, 0}
        };
        return pow(m, n - 1)[0][0];
    }

    public int[][] pow(int[][] m, int k) {
        // dp[0] = 1
        int[][] res = {
            {1, 0},
            {0, 0}
        };
        for (; k != 0; k /= 2) {
            if (k % 2 == 1) res = mul(m, res);
            m = mul(m, m);
        }
        return res;
    }

    public int[][] mul(int[][] x, int[][] y) {
        int[][] res = new int[2][2];
        for (int i = 0; i < 2; ++i) {
            for (int j = 0; j < 2; ++j) {
                res[i][j] = x[i][0] * y[0][j] + x[i][1] * y[1][j];
            }
        }
        return res;
    }
}

1137. 第 N 个泰波那契数

https://leetcode.cn/problems/n-th-tribonacci-number/

在这里插入图片描述
提示:
0 <= n <= 37
答案保证是一个 32 位整数,即 answer <= 2^31 - 1。

对矩阵稍作修改即可。

class Solution {
    public int tribonacci(int n) {
        if (n <= 1) return n;
        // m是根据递推公式来的
        int[][] m = {
            {1, 1, 1},
            {1, 0, 0},
            {0, 1, 0}
        };
        return pow(m, n - 2)[0][0];
    }

        public int[][] pow(int[][] m, int k) {
        // dp[0] = 0, dp[1] = 1, dp[2] = 1
        int[][] res = {
            {1, 0, 0},
            {1, 0, 0},
            {0, 0, 0}
        };
        for (; k != 0; k /= 2) {
            if (k % 2 == 1) res = mul(m, res);
            m = mul(m, m);
        }
        return res;
    }

    public int[][] mul(int[][] x, int[][] y) {
        int[][] res = new int[3][3];
        for (int i = 0; i < 3; ++i) {
            for (int j = 0; j < 3; ++j) {
                res[i][j] = x[i][0] * y[0][j] + x[i][1] * y[1][j] + x[i][2] * y[2][j];
            }
        }
        return res;
    }
}

1220. 统计元音字母序列的数目

https://leetcode.cn/problems/count-vowels-permutation/

在这里插入图片描述

提示:
1 <= n <= 2 * 10^4

解法1——线性DP

class Solution {
    final long MOD = (int)1e9 + 7;
    public int countVowelPermutation(int n) {
        long[][] dp = new long[n][5];
        Arrays.fill(dp[0], 1);
        for (int i = 1; i < n; ++i) {
            dp[i][0] = dp[i - 1][1];
            dp[i][1] = (dp[i - 1][0] + dp[i - 1][2]) % MOD;
            dp[i][2] = (dp[i - 1][0] + dp[i - 1][1] + dp[i - 1][3] + dp[i - 1][4]) % MOD;
            dp[i][3] = (dp[i - 1][2] + dp[i - 1][4]) % MOD;
            dp[i][4] = dp[i - 1][0];
        }
        long ans = 0;
        for (long x: dp[n - 1]) ans = (ans + x) % MOD;
        return (int)ans;
    }
}

解法2——矩阵快速幂优化DP

class Solution {
    final long MOD = (int)1e9 + 7;

    public int countVowelPermutation(int n) {
        long[][] m = {
            {0, 1, 0, 0, 0},
            {1, 0, 1, 0, 0},
            {1, 1, 0, 1, 1},
            {0, 0, 1, 0, 1},
            {1, 0, 0, 0, 0}
        };
        long[][] res = pow(m, n - 1);
        long ans = 0;
        for (int i = 0; i < 5; ++i) ans = (ans + res[i][0]) % MOD;
        return (int)ans;
    }

    public long[][] pow(long[][] m, int k) {
        long[][] res = {
            {1, 0, 0, 0, 0},
            {1, 0, 0, 0, 0},
            {1, 0, 0, 0, 0},
            {1, 0, 0, 0, 0},
            {1, 0, 0, 0, 0}
        };
        for (; k != 0; k /= 2) {
            if (k % 2 == 1) res = mul(m, res);
            m = mul(m, m);
        }
        return res;
    }

    public long[][] mul(long[][] x, long[][] y) {
        long[][] res = new long[5][5];
        for (int i = 0; i < 5; ++i) {
            for (int j = 0; j < 5; ++j) {
                res[i][j] = (x[i][0] * y[0][j] + x[i][1] * y[1][j] + x[i][2] * y[2][j] + x[i][3] * y[3][j] + x[i][4] * y[4][j]) % MOD;
            }
        }
        return res;
    }
}

552. 学生出勤记录 II(🚹递归公式 & 矩阵快速幂优化🐂)

https://leetcode.cn/problems/student-attendance-record-ii/
在这里插入图片描述
提示:
1 <= n <= 10^5

解法1——动态规划

class Solution {
    final int MOD = (int)1e9 + 7;

    public int checkRecord(int n) {
        // 长度,A 的数量,结尾连续 L 的数量
        int[][][] dp = new int[n + 1][2][3];    
        dp[0][0][0] = 1;
        for (int i = 1; i <= n; ++i) {
            // 以P结尾
            for (int j = 0; j < 2; ++j) {
                for (int k = 0; k < 3; ++k) {
                    dp[i][j][0] = (dp[i][j][0] + dp[i - 1][j][k]) % MOD;
                }
            }
            // 以A结尾
            for (int k = 0; k < 3; ++k) {
                dp[i][1][0] = (dp[i][1][0] + dp[i - 1][0][k]) % MOD;
            }
            // 以L结尾
            for (int j = 0; j < 2; ++j) {
                for (int k = 1; k < 3; ++k) {
                    dp[i][j][k] = (dp[i][j][k] + dp[i - 1][j][k - 1]) % MOD;
                }
            }
        }

        int ans = 0;
        for (int j = 0; j < 2; ++j) {
            for (int k = 0; k < 3; ++k) {
                ans = (ans + dp[n][j][k]) % MOD;
            }
        }
        return ans;
    }
}

解法2——矩阵快速幂优化DP(TODO)

在这里插入代码片

790. 多米诺和托米诺平铺⭐(🚹想出递推公式)

https://leetcode.cn/problems/domino-and-tromino-tiling/
在这里插入图片描述
提示:
1 <= n <= 1000

解法1——动态规划1 分最后一列的状态

https://leetcode.cn/problems/domino-and-tromino-tiling/solutions/1962465/duo-mi-nuo-he-tuo-mi-nuo-ping-pu-by-leet-7n0j/
在这里插入图片描述

class Solution {
    final int MOD = (int)1e9 + 7;

    public int numTilings(int n) {
        // 0空,1上,2下,3满
        int[][] dp = new int[n][4];
        dp[0][0] = dp[0][3] = 1;
        for (int i = 1; i < n; ++i) {
            dp[i][0] = dp[i - 1][3];
            dp[i][1] = (dp[i - 1][0] + dp[i - 1][2]) % MOD;
            dp[i][2] = (dp[i - 1][0] + dp[i - 1][1]) % MOD;
            dp[i][3] = (((dp[i - 1][0] + dp[i - 1][1]) % MOD + dp[i - 1][2]) % MOD + dp[i - 1][3]) % MOD;
        }
        return dp[n - 1][3];
    }
}

解法2——动态规划2 列出式子找通项公式(TODO 还没想明白)

https://leetcode.cn/problems/domino-and-tromino-tiling/solutions/1968516/by-endlesscheng-umpp/
在这里插入图片描述

class Solution {
    final long MOD = (long)1e9 + 7;

    public int numTilings(int n) {
        if (n <= 2) return n;
        long[] dp = new long[n + 1];
        dp[0] = 1;
        dp[1] = 1;
        dp[2] = 2;
        for (int i = 3; i <= n; ++i) {
            dp[i] = (dp[i - 1] * 2 + dp[i - 3]) % MOD;
        }
        return (int)dp[n];
    }
}

解法3——矩阵快速幂优化DP

class Solution {
    final int MOD = (int)1e9 + 7;

    public int numTilings(int n) {
        // 0空,1上,2下,3满
        long[][] m = {
            {0, 0, 0, 1},
            {1, 0, 1, 0},
            {1, 1, 0, 0},
            {1, 1, 1, 1}
        };
        return (int)pow(m, n - 1)[3][0];
    }

    public long[][] pow(long[][] m, int k) {
        long[][] res = {
            {1, 0, 0, 0},
            {0, 0, 0, 0},
            {0, 0, 0, 0},
            {1, 0, 0, 0}
        };
        for (; k != 0; k >>= 1) {
            if ((k & 1) == 1) res = mul(m, res);
            m = mul(m, m);
        }
        return res;
    }

    public long[][] mul(long[][] a, long[][] b) {
        long[][] c = new long[4][4];
        for (int i = 0; i < 4; ++i) {
            for (int j = 0; j < 4; ++j) {
                c[i][j] = (a[i][0] * b[0][j] + a[i][1] * b[1][j] + a[i][2] * b[2][j] + a[i][3] * b[3][j]) % MOD;
            }
        }
        return c;
    }
}

成绩记录

本次没有参加竞赛。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1017369.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

加密算法发展简介

1&#xff1a;对称加密算法 客户端加密数据和服务端解密数据&#xff0c;使用的相同的秘钥&#xff1a; 固定秘钥&#xff1a;双方约定好一个固定秘钥&#xff1b; 随机秘钥&#xff1a;双方约定每次建立连接的时候&#xff0c;某固定BYTE为秘钥&#xff1b; 缺点&#xff1a…

【MySQL】 MySQL数据库基础

文章目录 &#x1f431;‍&#x1f453;数据库的操作&#x1f4cc;显示当前的数据库&#x1f4cc;创建数据库&#x1f388;语法&#xff1a;&#x1f388;语法说明&#x1f388;示例&#xff1a; &#x1f334;使用数据库&#x1f38b;删除数据库&#x1f431;‍&#x1f3cd;语…

sql注入Less-2

后台sql s q l " S E L E C T ∗ F R O M u s e r s W H E R E i d sql "SELECT * FROM users WHERE id sql"SELECT∗FROMusersWHEREidid LIMIT 0,1"; 注入语句 http://192.168.200.26/Less-3/?id-1? union select 1,2,database();– 使用id-1 便可…

JavaScript中的Hoisting机制

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ JavaScript 中的 Hoisting 机制⭐ 变量提升⭐ 函数提升⭐ 注意事项⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xf…

LVS+Keepalived 高可用集群

LVSKeepalived 高可用集群 1、Keepalived工具介绍2、vrrp协议&#xff08;虚拟路由冗余协议&#xff09;2.1vrrrp是什么&#xff1f;2.2vrrp工作过程2.3Keeplived、VRRP及其工作原理2.4Keepalived体系主要模块 3、搭建LVSKeepalived 高可用集群 1、Keepalived工具介绍 支持故障…

MFC-GetSystemFirmwareTable获取系统固件表

获取ACPI表格 void CgetSystemFirmwareTableDlg::OnBnClickedButton1() {//UINT bufferSize GetSystemFirmwareTable(ACPI, 0, NULL, 0);//获取系统固件表/*【参数3和参数4为NULL和0&#xff0c;只是为了返回真实大小】这个函数可以用来获得系统中的各种固件信息&#xff0c;如…

MySQL中SQL语句执行顺序分析

1、 MySQL手写执行顺序 2、 MySQL机读执行顺序 随着Mysql版本的更新换代&#xff0c;其优化器也在不断的升级&#xff0c;优化器会分析不同执行顺序产生的性能消耗不同而动态调整执行顺序。下面是经常出现的查询顺序&#xff1a;

SpringBoot使用Mybatis查询数据

1.创建工程 说明&#xff1a;创建springboot工程&#xff0c;数据库表book&#xff0c;实体类Book 1.1创建项目 1.2 勾选相应的配置 1.3数据表book 说明&#xff1a;创建了book表&#xff0c;添加了id,type,name,description字段。 1.4创建Book实体类 说明&#xff1a;生成…

微服务保护-流控效果

个人名片&#xff1a; 博主&#xff1a;酒徒ᝰ. 个人简介&#xff1a;沉醉在酒中&#xff0c;借着一股酒劲&#xff0c;去拼搏一个未来。 本篇励志&#xff1a;三人行&#xff0c;必有我师焉。 本项目基于B站黑马程序员Java《SpringCloud微服务技术栈》&#xff0c;SpringCloud…

【AI】推理系统和推理引擎的整体架构

本文主要是对 B 站 Up 主 ZOMI酱 推理系统系列视频 的理解&#xff0c;可以认为是重点笔记。 一、深度学习模型的全生命周期 相信很多人和我一样&#xff0c;刚看到深度学习模型中的推理系统或推理引擎时是一头雾水&#xff0c;因为学习 DL 时通常关注于模型的设计和训练。下图…

MFC - 一文带你从小白到项目应用(全套1)

文章篇幅可能会比较长&#xff0c;从入门到基本能上项目的全部内容。建议观看的过程中&#xff0c;用电脑跟着学习案例。 持续输出优质文章是作者的追求&#xff0c;因为热爱&#xff0c;所以热爱。 最近看动漫被一句鸡汤感动到了&#xff0c;也送给各位朋友&#xff1a; 只要有…

微服务保护-热点参数限流

个人名片&#xff1a; 博主&#xff1a;酒徒ᝰ. 个人简介&#xff1a;沉醉在酒中&#xff0c;借着一股酒劲&#xff0c;去拼搏一个未来。 本篇励志&#xff1a;三人行&#xff0c;必有我师焉。 本项目基于B站黑马程序员Java《SpringCloud微服务技术栈》&#xff0c;SpringCloud…

Dubbo3基础使用

1、Dubbo概述 现在SpringCloud Alibaba比较火&#xff0c;用的比较多是吧&#xff0c;那dubbo是不是过时的呢&#xff1f; 并不是的&#xff0c;以前有人把Dubbo和SpringCloud进行对比&#xff0c;其实两者是不同维度的&#xff0c;不能对比&#xff0c;dubbo就是一个rpc框架&…

Adobe Bridge 2024:解锁创意力的数字媒体利器

在当今数字化的时代&#xff0c;创意工作者们需要处理和管理大量的数字媒体资源&#xff0c;如照片、视频、音频等。为了提高工作效率和创作质量&#xff0c;他们需要一个功能强大、易于使用的工具来组织、浏览和共享这些媒体文件。幸运的是&#xff0c;Adobe Bridge 2024 正好…

Linux文件类型与根目录结构

目录 一、文件类型 二、目录结构 1、FHS Linux目录结构的特点 2、路径以及工作目录 1&#xff09;路径 2&#xff09;工作目录 3&#xff09;存放路径 一、文件类型 主目录下部分文件如下&#xff1a; [rootlocalhost ~]# cd ~ [rootlocalhost ~]# ll total 52 -rw-r--…

烟雾报警系统设计与实现

摘要 随着“信息时代”的到来&#xff0c;作为获取信息的手段——传感器技术得到了显著的进步&#xff0c;其应用领域越来越广泛&#xff0c;对其要求越来越高&#xff0c;需求越来越迫切。传感器技术已成为衡量一个国家科学技术发展水平的重要标志之一。因此&#xff0c;了解…

不可思议,无密码登录所有网站!

hello&#xff0c;我是小索奇 居然可以免密码登录你的网站&#xff1f;听起来是不是很恐怖 确实如此&#xff0c;Cookie可以用于保持用户在网站上的登录状态&#xff0c;从而实现 免密码登录&#xff0c;学会了不要做坏事哈 这里仅做免密码登录的实操&#xff0c;就不介绍Cooki…

如何从第一性原则的原理分解数学问题

如何从第一性原则的原理分解数学问题 摘要&#xff1a;牛津大学入学考试题目展示了所有优秀数学家都使用的系统的第一原则推理&#xff0c;而GPT4仍然在这方面有困难 作者&#xff1a;Keith McNulty 我们中的许多人都熟悉直角三角形的边的规则。根据毕达哥拉斯定理&#xff0c;…

动态的中秋爱心演示送女友用python生成爱心软件文末附c++语言写法

用python生成爱心软件 用python生成动态爱心软件 目录 用python生成爱心软件 完整代码 代码解释 逐句解释 效果展示&#xff1a; 如何打包 c写法 完整代码 import turtledef draw_heart():love turtle.Turtle()love.getscreen().bgcolor("black")love.…

python使用execjs利用jsdom来执行含有document的js代码方案(上)

先说一下环境&#xff1a;win7 64位&#xff0c;python3.8.10。 python使用execjs执行含有document的js代码时&#xff0c;会出现报错&#xff1a; execjs._exceptions.ProgramError: TypeError: document 未定义 原因是纯js代码中是不包含浏览器里对象的(如document、windo…