文章目录
竞赛链接
https://leetcode.cn/contest/biweekly-contest-117/
Q1:2928. 给小朋友们分糖果 I
https://leetcode.cn/problems/distribute-candies-among-children-i/description/
提示:
1 <= n <= 50
1 <= limit <= 50
竞赛时代码
拆分问题,枚举第一个人的糖果数,累加 另外两人的方案数。
class Solution {
public int distributeCandies(int n, int limit) {
int ans = 0;
// 枚举分给第一个小朋友的糖果
for (int i = 0; i <= Math.min(n, limit); ++i) {
ans += op(n - i, limit);
}
return ans;
}
// 计算两个人分n个糖果的方案数
public int op(int n, int l) {
// 计算可获得的最小值和最大值,另一个人随之确定
int mx = Math.min(n, l), mn = Math.max(n - l, 0);
return Math.max(0, mx - mn + 1);
}
}
Q2:100127. 给小朋友们分糖果 II
https://leetcode.cn/problems/distribute-candies-among-children-ii/description/
提示:
1 <= n <= 10^6
1 <= limit <= 10^6
竞赛时代码——枚举第一个人,求两个人的最大值最小值
class Solution {
public long distributeCandies(int n, int limit) {
long ans = 0;
// 枚举分给第一个小朋友的糖果
for (int i = 0; i <= Math.min(n, limit); ++i) {
ans += op(n - i, limit);
}
return ans;
}
// 计算两个人分n个糖果的方案数
public long op(int n, int l) {
// 计算可获得的最小值和最大值,另一个人随之确定
int mx = Math.min(n, l), mn = Math.max(n - l, 0);
return Math.max(0, mx - mn + 1);
}
}
解法2—— O ( 1 ) O(1) O(1) 容斥原理🐂
合法方案数 = 总方案数 - 不合法方案数
n + 2
n - (limit + 1) + 2
n - 2 * (limit + 1) + 2
n - 3 * (limit + 1) + 2
class Solution {
public int distributeCandies(int n, int limit) {
int a = c2(n + 2); // n+2的位置放2个板子
int b = 3 * c2(n - limit + 1); // 至少一个>limit的情况
int c = 3 * c2(n - 2 * limit); // 至少两个>limit的情况
int d = c2(n - 3 * limit - 1); // 至少三个>limit的情况
return a - b + c - d;
}
public int c2(int n) {
return n > 1? n * (n - 1) / 2: 0;
}
}
Q3:2930. 重新排列后包含指定子字符串的字符串数目⭐⭐⭐⭐⭐(数学、容斥原理)
提示:
1 <= n <= 10^5
解法—— O ( l o g n ) O(log n) O(logn) 容斥原理⭐⭐⭐⭐⭐
https://leetcode.cn/problems/number-of-strings-which-can-be-rearranged-to-contain-substring/solutions/2522964/olog-n-rong-chi-yuan-li-fu-ji-yi-hua-sou-okjf/
总共的方案数:
2
6
n
26^n
26n
不满足的方案数:
不含 l、不含t、不含e、只含一个e
- 不含l: 2 5 n 25^n 25n
- 不含t: 2 5 n 25^n 25n
- 不含e 或 只含一个e: 2 5 n 25^n 25n + n ∗ 2 5 n − 1 n*25^{n-1} n∗25n−1
重复了两个组合需要去掉
- 不含 l 和 t: 2 4 n 24^n 24n
- 不含 l 和 e 最多含一个: 2 4 n + n ∗ 2 4 n − 1 24^n+n*24^{n-1} 24n+n∗24n−1
- 不含 t 和 e 最多含一个: 2 4 n + n ∗ 2 4 n − 1 24^n+n*24^{n-1} 24n+n∗24n−1
重复了两两组合的两两组合
- 不含 l 和 t 且 e 最多含一个: 2 3 n + n ∗ 2 3 ( n − 1 ) 23^n+n*23^{(n-1)} 23n+n∗23(n−1)
最后结果为
2
6
n
−
{
2
5
n
+
2
5
n
+
2
5
n
+
n
∗
2
5
n
−
1
−
2
4
n
−
2
4
n
−
n
∗
2
4
n
−
1
−
2
4
n
−
n
∗
2
4
n
−
1
+
2
3
n
+
n
∗
2
3
(
n
−
1
)
}
26^n-\{25^n+25^n + 25^n + n*25^{n-1} -24^n-24^n-n*24^{n-1}-24^n-n*24^{n-1}+23^n+n*23^{(n-1)}\}
26n−{25n+25n+25n+n∗25n−1−24n−24n−n∗24n−1−24n−n∗24n−1+23n+n∗23(n−1)}
=
2
6
n
−
3
∗
2
5
n
−
n
∗
2
5
n
−
1
+
3
∗
2
4
n
+
2
∗
n
∗
2
4
n
−
1
−
2
3
n
−
n
∗
2
3
n
−
1
26^n-3*25^n-n*25^{n-1}+3*24^n+2*n*24^{n-1}-23^n-n*23^{n-1}
26n−3∗25n−n∗25n−1+3∗24n+2∗n∗24n−1−23n−n∗23n−1
=
2
6
n
−
(
3
∗
25
+
n
)
∗
2
5
n
−
1
+
(
3
∗
24
+
2
∗
n
)
∗
2
4
n
−
1
−
(
23
+
n
)
2
3
n
−
1
26^n-(3*25+n)*25^{n-1}+(3*24+2*n)*24^{n-1}-(23+n)23^{n-1}
26n−(3∗25+n)∗25n−1+(3∗24+2∗n)∗24n−1−(23+n)23n−1
转换成代码如下:
class Solution {
final long MOD = (long)1e9 + 7;
public int stringCount(int n) {
long ans = ((pow(26, n) - pow(25, n - 1) * (75 + n) + pow(24, n - 1) * (72 + 2 * n) - pow(23, n - 1) * (23 + n)) % MOD + MOD) % MOD;
return (int)ans;
}
public long pow(long x, long n) {
long res = 1;
while (n != 0) {
if (n % 2 == 1) res = (res * x) % MOD;
x = (x * x) % MOD;
n >>= 1;
}
return res;
}
}
Q4:2931. 购买物品的最大开销(贪心)
https://leetcode.cn/problems/maximum-spending-after-buying-items/description/
提示:
1 <= m == values.length <= 10
1 <= n == values[i].length <= 10^4
1 <= values[i][j] <= 10^6
values[i] 按照非递增顺序排序。
竞赛时代码——贪心
每次先取最小的购买即可。
class Solution {
public long maxSpending(int[][] values) {
long ans = 0;
int m = values.length, n = values[0].length;
int[] idx = new int[m];
Arrays.fill(idx, n - 1);
for (long d = 1; d <= m * n; ++d) {
int id_m = 0;
for (int i = 0; i < m; ++i) {
if (idx[i] >= 0) {
id_m = i;
break;
}
}
for (int i = 0; i < m; ++i) {
if (idx[i] >= 0 && values[i][idx[i]] < values[id_m][idx[id_m]]) id_m = i;
}
ans += d * values[id_m][idx[id_m]];
idx[id_m]--;
}
return ans;
}
}
优化——一起排序
注意到题目中 第 i 个商店的物品已经按照价值非递增排好序了
。
因此,
可以把所有的数字一起排序。
class Solution {
public long maxSpending(int[][] values) {
int m = values.length, n = values[0].length;
int[] a = new int[m * n];
int i = 0;
for (int[] row : values) {
System.arraycopy(row, 0, a, i, n);
i += n;
}
Arrays.sort(a);
long ans = 0;
for (i = 0; i < a.length; i++) {
ans += (long) a[i] * (i + 1);
}
return ans;
}
}
成绩记录
T3 没想出来怎么写。