LeetCode252周赛
LeetCode
来源: LeetCode252周赛
以为是晚上十点半开始,结果傻眼了,是中午十点半
第一题
暴力直接过
class Solution {
public:
bool isThree(int n) {
int res = 0;
for(int i = 1;i <= n;i++){
if(n % i == 0) res++;
}
return res == 3;
}
};
第二题
这道题咋一看会以为我从大到小挨着来就行了呗,其实不行
我可以一周换一次任务去做,那么我们考虑,所以任务数量的最大值和任务的数量的总数
我们考虑当最大值小于等于总数减去最大值的时候,那么除了最大值那个项目,最少还要有两个项目,如果只要一个,那么与我们当前最大值冲突,所以最少还有两个,那么我们在这几个项目里,一定可以你一个我一个他一个在内部消化,然后使得这些剩余的总数等于最大值,这时,再交替进行,一定可以全部完成
当最大值大于总数减去最大值,根据上面我们知道,我们一定无法全部完成,因为就算把所有最大值除外的跟最大值交替进行,也无法完成最大的那个,那外面考虑可以完成多少,sum表示总和,maxx表示最大值,那我们一定可以完成(sum - maxx) * 2
,然后我们先完成最大的,这样我们最后还可以再完成一次最大的,所以我们可以完成(sum - maxx) * 2 + 1
这么多,所以当最大值等于总数减去最大值 + 1也可以全部完成
这里可能讲的不够清楚,有点绕
typedef long long ll;
class Solution {
public:
long long numberOfWeeks(vector<int>& m) {
ll maxx = 0, sum = 0;
for(auto i : m){
if(i > maxx) maxx = i;
sum += i;
}
if(maxx > (sum - maxx + 1)) return (sum - maxx) * 2 + 1;
return sum;
}
};
第三题
经典找规律
列公式
这里解释一下官方题解,由于图形的对称的,所以x可以取到的y也可以取到,所以就是2倍的只对x求和,其实y是从-n到n,一共有2n + 1种选择,所以乘以(2n + 1),最后对于x,从-n到n求和,也就是(((1 + n) * n) / 2) * 2,所以化简成2n(n + 1)(2n + 1)
我上面也说了,可以找规律,所以我是找规律写的
可以说是很笨了,就不讲了,还是列公式简单
下面是我自己的代码,可以琢磨一下我是怎么找规律的,其实也很简单
typedef long long ll;
class Solution {
public:
long long minimumPerimeter(long long neededApples) {
ll i;
ll k = 0;
for(i = 1;i <= 1e7;i++){
if((i * i + k) * (ll)12 >= neededApples) break;
k += i * i;
}
return i * 8;
}
};
第四题
规定的子序列,一般就是dp了,这道题比较简单
定义F数组
f[0]表示以0结尾的子序列当前的最大值
f[1]表示以1结尾的子序列当前的最大值
f[0]表示以2结尾的子序列当前的最大值
遍历数组
如果当前是0,那么从初始位置到当前位置,以0位结尾的子序列数就是f[0] = ((f[0] * 2) % mod + 1) % mod;
表示原先以0为结尾的,那么这些就可以跟我当前这个0再各构成一次,我当前0也可以单独构成一次
同理,如果当前是1,f[1] = ((f[1] * 2) % mod + f[0]) % mod;
表示原先以1结尾的子序列,这些子序列与我当前1构成的子序列,再加上前面以0结尾的子序列,因为我的1可以和他们构成以1结尾的子序列
同理,如果当前为2,f[2] = ((f[2] * 2) % mod + f[1]) % mod;
class Solution {
public:
int f[3];
const int mod = 1e9 + 7;
int countSpecialSubsequences(vector<int>& nums) {
for(auto i : nums){
if(i == 0) f[0] = ((f[0] * 2) % mod + 1) % mod;
else if(i == 1) f[1] = ((f[1] * 2) % mod + f[0]) % mod;
else f[2] = ((f[2] * 2) % mod + f[1]) % mod;
}
return f[2];
}
};