反思
平时没有常规刷题到了周赛就明显感觉手生了,加上早上没睡醒,签到题都做了10min。今天的题难度不大,但是却做得很烂。希望能给自己打一剂鸡血,常规练习不能偷懒。
题解
三除数
直接模拟,统计一共有多少个除数,判断是否为3。
Code Q1
class Solution {
public:
bool isThree(int n) {
int cnt = 0;
for (int i = 1; i <= n; i++) {
if (n % i == 0) cnt ++;
}
return cnt == 3;
}
};
你可以工作的最大周数
这个贪心以前没有见过,考试想了很久也没有想出来。
可以看最大值和余下值的关系。
- 如果最大值小于等于总和的一半,也就是说最大值小于等于余下值之和,那么总可以完成所有任务。如何完成呢?我们采用以下策略。
- 记最大值为$m$,余下值中的最大值为$k$,当$m > k$时,将全体值分为2组,一组为最大值,一组为余下值,先执行$m$所在的任务,再执行$k$所在任务(注意,这里的$k$所在任务可能会变化),直到$m = k$;
- 当$m = k$时,先执行$m$所在任务,然后将$m$任务与$k$交换位置。这样操作可以保证,在执行最大值这一组时$m$不变,亦保证了最大值组始终为全局最大值。
- 重复1,2直到结束,所有的任务都将完成。
- 如果最大值大于总和一半。那么同样将所有值分为最大值组和余下值组,先执行最大值组,这样最后会剩下最大值组没有执行完。执行次数应该为$2 * (sum - m) + 1$。
Code Q2
using LL = long long;
class Solution {
public:
long long numberOfWeeks(vector<int>& milestones) {
LL sum = 0, m = 0;
for (LL x : milestones) {
m = max(m, x);
sum += x;
}
if (m > sum - m) return 2 * (sum - m) + 1; // 不能完成
return sum; // 能完成
}
};
收集足够苹果的最小花园周长
简单的推公式题,可以推出第$n$层外围的苹果数量为$12n^2$。
Code Q3
class Solution {
public:
long long minimumPerimeter(long long t) {
long long sum = 0;
for (int i = 1; ;i++) {
sum += 12 * (long long)i * i;
if (sum >= t) return 8 * (long long)i;
}
return sum;
}
};
统计特殊子序列的数目
设f[i][j]
为从0~i
中取,j
型序列的数量。j
的取值为0,1,2
,分别表示:
- 全都是0;
- 连续0 + 连续1;
- 连续0 + 连续1 + 连续2 (特殊序列)。
考虑状态转移:
类型0:用第
i
个数是否属于之前子序列作为划分,可以将0放到之前的全0序列后面,这样又多了f[i - 1][0]
个新的子序列;同时,也可以把自己当成一个序列(不属于前面任何序列),这样多了1个新序列。f[i][0] = 2 * f[i - 1][0] + 1
类型1:同理。用第
i
个数是否属于之前子序列作为划分,可以将1放到之前的类型1序列后面,这样又多了f[i - 1][1]
个新的子序列;同时,也可以放到全0序列后面,这样多了f[i - 1][0]
个新序列。f[i][1] = 2 * f[i - 1][1] + f[i - 1][0]
类型2:同理。用第
i
个数是否属于之前子序列作为划分,可以将1放到之前的类型2序列后面,这样又多了f[i - 1][2]
个新的子序列;同时,也可以放到类型1序列后面,这样多了f[i - 1][1]
个新序列。f[i][2] = 2 * f[i - 1][2] + f[i - 1][1]
Code Q4
class Solution {
public:
int countSpecialSubsequences(vector<int>& nums) {
int n = nums.size();
const int MOD = 1e9 + 7;
vector<vector<int>> f(n + 1, vector<int>(3, 0));
for (int i = 1; i <= n; i++) {
int x = nums[i - 1];
if (x == 0) {
f[i][0] += (2 * f[i - 1][0] % MOD + 1) % MOD;
f[i][1] = f[i - 1][1];
f[i][2] = f[i - 1][2];
} else if (x == 1) {
f[i][1] = (2 * f[i - 1][1] % MOD + f[i - 1][0]) % MOD;
f[i][0] = f[i - 1][0];
f[i][2] = f[i - 1][2];
} else {
f[i][2] = (2 * f[i - 1][2] % MOD + f[i - 1][1]) % MOD;
f[i][1] = f[i - 1][1];
f[i][0] = f[i - 1][0];
}
}
return f[n][2];
}
};
- Post link: https://scnujackychen.github.io/2021/08/01/LC-weekly-contest-252/
- Copyright Notice: All articles in this blog are licensed under unless otherwise stated.
若没有本文 Issue,您可以使用 Comment 模版新建。
GitHub IssuesGitHub Discussions