[CP / Codeforces] Codeforces Round 929 (Div. 3) A-E
最近不打算做新的题目了,先把之前打过的 contest 的题目都补完。我今天才发现,自己一直以来都陷入了这样一个误区,认为自己的水平还不够,经验积累得还不多,因此不能做高于 1900* 的题目……现在想来这个理由真是莫名其妙。如果不主动去做那些题,怎么积累相关的经验呢?
以上这些话与本文无关,只是想到了就写一写。
A. Turtle Puzzle: Rearrange and Negate
分析
\[ans=\sum\limits_{i=1}^{n}|a_i|
\]
代码
void solve() {
int n, t, ans = 0;
std::cin >> n;
for (int i = 0; i < n; i++) {
std::cin >> t;
if (t < 0)
t = -t;
ans += t;
}
std::cout << ans << '\n';
}
B. Turtle Math: Fast Three Task
分析
先对输入数组求和,记求和结果为 \(s\) ,分类讨论:
- \(s\mod{}3=0\):直接输出 0。
- \(s\mod{}3=1\):如果数组中存在元素 \(t\) 满足 \(3\ |\ (t-1)\),则去掉此元素就能使最后结果被 3 整除,所以输出 1;否则输出 2。
- \(s\mod{}3=2\):对数组中的任意数加 1 就能使最后结果被 3 整除,所以输出 1。
代码
void solve() {
int n, t, sum = 0;
bool flag = false;
std::cin >> n;
for (int i = 0; i < n; i++) {
std::cin >> t;
if ((t - 1) % 3 == 0)
flag = true;
sum += t;
}
if (sum % 3 == 0)
std::cout << "0\n";
else if (sum % 3 == 2 || flag)
std::cout << "1\n";
else
std::cout << "2\n";
}
C. Turtle Fingers: Count the Values of k
分析
因为数据范围不大,所以可以暴力枚举 \(x,y\) 所有可能的组合,然后判断是否满足 \(a^xb^y\ |\ l\),若满足则计算出 \(k=\frac{l}{a^xb^y}\) 并放入 unordered_set 中去重。
代码
void solve() {
i64 l, a, b, ax = 1, by;
std::cin >> a >> b >> l;
std::unordered_set<int> ans;
for (i64 x = 0; x <= 20; x++) {
if (ax > l)
break;
by = 1;
for (i64 y = 0; y <= 20; y++) {
if (by > l)
break;
i64 m = ax * by;
if (l % m == 0)
ans.insert(l / m);
by *= b;
}
ax *= a;
}
std::cout << ans.size() << '\n';
}
D. Turtle Tenacity: Continual Mods
分析
首先对输入数组从小到大排序。如果数组元素各异,那么可以直接从头到尾取余下去,因为每次取余的结果都比下一个数小,所以结果必然非零,并且等于第一次取余的结果;如果最小的元素重复,以 \([2,2,2,3,4,4,5,5,5,6,6]\) 为例,若按照先前的方法取余,一开始就会产生 \(0\),所以需要想办法让第一次取余的结果不被 2 整除。
因为
\[a \mod{} b=c < b
\]
且
\[0 \mod{} a \equiv{} 0
\]
所以,只需要想办法在输入数组中找到一个数 \(k\) ,满足 \(k \mod{} 2 \neq{} 0\),以这个结果作为第一次取余的结果,再从头到尾取余下去,就不会产生 \(0\)。
对于本例来说,可以取 \(3\) 作为这样的 \(k\),并将原数组安排为如下顺序:\([3,2,2,2,4,4,5,5,5,6,6]\),第一次取余将产生 \(1\),此结果之后不再发生变化。
代码
void solve() {
int n, t;
std::cin >> n;
bool flag = true;
std::map<int, int> m;
for (int i = 0; i < n; i++) {
std::cin >> t;
++m[t];
if (flag && m[t] >= 2)
flag = false;
}
if (flag || m.begin()->second == 1) {
std::cout << "YES\n";
return;
}
int p = m.begin()->first;
for (const auto &[num, cnt] : m) {
if (num % p != 0) {
std::cout << "YES\n";
return;
}
}
std::cout << "NO\n";
}
E. Turtle vs. Rabbit Race: Optimal Trainings
分析
注意到我们寻找的目标随着下标的递增,具有先单调增,后单调减的性质,也就是所谓的极大值,故使用二分解决。
代码
void solve() {
int n;
std::cin >> n;
std::vector<int> v(n + 1);
for (int i = 1; i <= n; i++) {
std::cin >> v[i];
v[i] += v[i - 1];
}
int q, l, u, L, R, M;
auto f = [&](int M) {
int s1 = v[M] - v[l - 1];
int s2 = v[M - 1] - v[l - 1];
return 1LL * (2 * u + 1 - s1) * s1 > 1LL * (2 * u + 1 - s2) * s2;
};
std::cin >> q;
for (int i = 0; i < q; i++) {
std::cin >> l >> u;
L = l + 1, R = n;
while (L <= R) {
M = (L + R) >> 1;
if (f(M))
L = M + 1;
else
R = M - 1;
}
std::cout << R << '\n';
}
}

浙公网安备 33010602011771号