本文主要把近期 \(CF-Div.2\) 的 \(A,B,C,D\) 题进行做
Round 815
A
题意
给你两个分数 \(\frac{a}{b},\frac{c}{d}\) ,问你最少几次使两个分数相等。
Solution
首先考虑,最大的情况为 \(2\) ,(两个分子都 \(\times 0\) 不就相等了),如果输入的分数相等,答案就是 \(0\) ,否则就不可能是 \(0\) 。
让我们假设,为了使分数在 \(1\) 次操作中相等,我们必须将第一个数的分数乘以 \(x\)。那么 \(\frac{ax}{b}=\frac{c}{d} \Rightarrow x=\frac{bc}{ad}\),检验一下能被整除即可。
if (x == y)
cout << "0\n";
else if (y != 0 && x % y == 0 || x != 0 && y % x == 0)
cout << "1\n";
else
cout << "2\n";
B
题意
给你一个数列 \(a_n\) ,选一个 \(l,r\) ,使得下式最大化:
\[\max(a_1,a_2,…,a_{l−1},a_{r+1},a_{r+2},…,a_{n})−\min(a_1,a_2,…,a_{l−1},a_{r+1},a_{r+2},…,a_{n})+\max(a_l,…,a_r)−\min(a_l,…,a_r) \]Solution
显然,答案不超过 \(max_1+max_2-min_1-min_2\) ,其中 \(max_1,max_2\) 是数组中两个最大值, \(min_1,min_2\) 是两个最小值。
那么答案就是这个。
时间复杂度 \(O(n)\) 或者 \(O(n \log n)\)
C
题意
有一个由 \(0\) 和 \(1\) 组成的矩阵。
每次操作可以选择一个 \(2\times 2\) 的子矩阵,在这个子矩阵中选择一个 L
形,将这个 L
形里的 \(3\) 个数变成 0
,注意,这个 L
形至少含有一个 \(1\) ,你想最大化操作个数,问最多操作多少次。
Solution
由于可能初始矩阵中没有一个位置可以做到一次操作仅消除一个 \(1\) ,所以我们要找到消除 \(1\) 数量最小的第一次操作,从第二次操作开始就可以做到每次消除一个 \(1\) 。先统计矩阵中 \(1\) 的个数,记为 \(sum\) ,若为 \(0\) ,则无法操作,输出 \(0\) 。否则枚举每个位置,并统计以这个位置为每一种形状的 L
形的角时,L
形内 \(1\) 的个数,只要这个个数大于 \(0\)(因为每次操作的 \(L\) 形中至少一个 \(1\) ),就将其比较并更新变量 \(Min\) 。最后 \(Min\) 就是最佳的第一次操作所消除的 \(1\) 的个数。答案即为 \(sum-Min+1\) 。
其实只要 check 一下有没有横着或者竖着的连着的两个 0
如果有,\(Min = 1\) ,若没有,\(Min = 2\) .
D
题意
Solution
for (int j = 1; j <= n; j++){
dp[j] = 0;
for (int k = max(j - M, 1); k < j; k++){
if ((a[j] ^ (k - 1)) > (a[k] ^ (j - 1))) dp[j] = max(dp[j], dp[k]);
}
ans = max(ans, ++dp[j]);
}