6337. Count Distinct Numbers on Board

给你一个正整数 n ,开始时,它放在桌面上。在 109 天内,每天都要执行下述步骤:

  • 对于出现在桌面上的每个数字 x ,找出符合 1 <= i <= n 且满足 x % i == 1 的所有数字 i 。
  • 然后,将这些数字放在桌面上。
    返回在 10^9 天之后,出现在桌面上的 不同 整数的数目。

注意:

  • 一旦数字放在桌面上,则会一直保留直到结束。
  • % 表示取余运算。例如,14 % 3 等于 2 。

测试样例

输入:n = 5

输出:4

解释:

最开始,5 在桌面上。 第二天,2 和 4 也出现在桌面上,因为 5 % 2 == 1 且 5 % 4 == 1 。 再过一天 3 也出现在桌面上,因为 4 % 3 == 1 。 在十亿天结束时,桌面上的不同数字有 2 、3 、4 、5 。

解答:这题关键条件是

  1. 找出符合 1 <= i <= n
  2. 1 <= n <= 100

暴力计算即可

class Solution {
    public int distinctIntegers(int n) {
        boolean[] isAdd = new boolean[101];
        isAdd[n] = true;
        Queue<Integer> queue = new LinkedList<>();
        queue.add(n);
        int res = 1;

        while (!queue.isEmpty()) {
            int tmp = queue.poll();
            for (int i = 1; i <= tmp; ++i) {
                if (tmp % i == 1 && !isAdd[i]) {
                    isAdd[i] = true;
                    queue.add(i);
                    res += 1;
                }
            }
        }
        return res;
    }
}

6338. Count Collisions of Monkeys on a Polygon

现在有一个正凸多边形,其上共有 n 个顶点。顶点按顺时针方向从 0 到 n - 1 依次编号。每个顶点上 正好有一只猴子 。下图中是一个 6 个顶点的凸多边形。

每个猴子同时移动到相邻的顶点。顶点 i 的相邻顶点可以是:

  • 顺时针方向的顶点 (i + 1) % n ,或
  • 逆时针方向的顶点 (i - 1 + n) % n 。
    如果移动后至少有两个猴子位于同一顶点,则会发生 碰撞 。

返回猴子至少发生 一次碰撞 的移动方法数。由于答案可能非常大,请返回对 10^9+7 取余后的结果。

注意,每只猴子只能移动一次。

测试样例:

输入:n = 3

输出:6

解答: 这道题本质考的是快速幂。如果猴子想要不发生任何碰撞,只有2种可能,即猴子同时顺时针移动或者逆时针一动。

所以答案就是所有可能 - 2

class Solution {
    private static final int mod = 1_000_000_007;

    public int monkeyMove(int n) {
        long all = mul(n);
        return (int)((all + mod - 2) % mod);
    }

    private long mul(int n) {
        if (n == 0) {
            return 1;
        } else {
            long tmp = mul(n / 2);
            long cur = 1;
            if (n % 2 == 1) {
                cur = 2;
            }
            return (tmp * tmp * cur) % mod;
        }
    }
}

6339. Put Marbles in Bags

你有 k 个背包。给你一个下标从 0 开始的整数数组 weights ,其中 weights[i] 是第 i 个珠子的重量。同时给你整数 k 。

请你按照如下规则将所有的珠子放进 k 个背包。

  • 没有背包是空的。
  • 如果第 i 个珠子和第 j 个珠子在同一个背包里,那么下标在 i 到 j 之间的所有珠子都必须在这同一个背包中。
  • 如果一个背包有下标从 i 到 j 的所有珠子,那么这个背包的价格是 weights[i] + weights[j] 。
    一个珠子分配方案的 分数 是所有 k 个背包的价格之和。

请你返回所有分配方案中,最大分数 与 最小分数 的 差值 为多少。

测试样例

输入:weights = [1,3,5,1], k = 2

输出:2

解答:这题是脑筋急转弯题。一开始会以为使用动态规划,但是直接超时,所以需要换个思路。

由于每个背包,可以认为是一次数组的切分。那么经过一次切分之后,切切分在i位置,则增加的分数是nums[i] + nums[i + 1]。那么最小分数和最大分数就是寻找最大的K - 1个切分位和最小的K - 1个切分位置。

class Solution {
    public long putMarbles(int[] weights, int k) {
        List<Long> list = new ArrayList<>();
        for (int i = 0; i + 1 < weights.length; ++i) {
            long tmp = weights[i];
            tmp += weights[i + 1];
            list.add(tmp);
        }
        Collections.sort(list);
        long res = 0;
        for (int i = 0; i < k - 1; ++i) {
            res -= list.get(i);
            res += list.get(list.size() - 1 - i);
        }
        return res;
    }
}

6340. Count Increasing Quadruplets

给你一个长度为 n 下标从 0 开始的整数数组 nums ,它包含 1 到 n 的所有数字,请你返回上升四元组的数目。

如果一个四元组 (i, j, k, l) 满足以下条件,我们称它是上升的:

  • 0 <= i < j < k < l < n 且
  • nums[i] < nums[k] < nums[j] < nums[l] 。

测试样例

输入:nums = [1,3,2,4,5]

输出:2

解答:这种寻找3个或者4个关键数字的题目基本有个套路 - 从中间的一个/两个数字下手,分为前半和后半部分。

以这道题目为例子,我们从j,k入手。则我们需要寻找比nums[k]小,且i < j的个数和寻找比nums[j]大,且n > l的个数。以此转化为2个二维前缀和就能获得答案。

class Solution {
    public long countQuadruplets(int[] nums) {
        int len = nums.length;
        int[][] countLarge = new int[len][len];
        for (int i = 0; i < len; ++i) {
            int tmp = 0;
            for (int j = len - 1; j > i; --j) {
                if (nums[j] < nums[i]) {
                    countLarge[i][j] = tmp;
                } else if (nums[j] > nums[i]) {
                    tmp += 1;
                }
            }
        }

        long res = 0;
        for (int i = 0; i < len; ++i) {
            long tmp = 0;
            for (int j = 0; j < i; ++j) {
                if (nums[j] > nums[i]) {
                    res += tmp * countLarge[j][i];
                } else if (nums[j] < nums[i]) {
                    ++tmp;
                }
            }
        }
        return res;
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *