A.Turtle Puzzle: Rearrange and Negate (思维)
题意:
给出一个长度为nnn的数组aaa,可以选择进行以下两种操作:
- 将数组随机打乱
- 选择一段区间并取反
询问经过操作之后,数组和最大是多少。
分析:
通过操作可以将所有负数集中到一个区间,然后再进行翻转,所以数组和最大就是所有元素绝对值相加。
代码:
#include <bits/stdc++.h>
using namespace std;
int main() {
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
int sum = 0;
for (int i = 1; i <= n; i++) {
int x;
cin >> x;
sum += abs(x);
}
cout << sum << endl;
}
return 0;
}
B.Turtle Math: Fast Three Task (模拟)
题意:
给定一个长度为nnn的数组aaa,你可以进行以下两种操作:
- 删除数组中的一个元素
- 选择其中一个元素,将它的值加111
你可以执行任意次上述操作,询问至少需要多少次操作可以使得最终数组总和能被333整除。
分析:
分情况讨论:
-
本身被333整除,无需操作
-
模333余111,查找是否有元素模333余111,如果有就删除
-
模333余222,任选一个元素加111
-
其他情况都需要两次操作。
代码:
#include <bits/stdc++.h>
using namespace std;
int main() {
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
int sum = 0;
int flag = 0;
for (int i = 1; i <= n; i++) {
int x;
cin >> x;
if (x % 3 == 1)
flag = 1;
sum += x;
}
sum %= 3;
if (sum) {
if ((sum == 1 && flag) || (sum == 2)) {
sum = 1;
} else {
sum = 2;
}
}
cout << sum << endl;
}
return 0;
}
C. Turtle Fingers: Count the Values of k (数学)
题意:
询问存在多少种非负整数kkk,使得在k,x,yk,x,yk,x,y都是非负数的情况,满足下列等式:
- l=k×ax×byl=k \times a^x \times b^yl=k×ax×by
分析:
直接枚举x,yx,yx,y,并用setsetset对kkk去重。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int main() {
int t;
cin >> t;
while (t--) {
LL a, b, l;
cin >> a >> b >> l;
vector<LL> x, y;
LL s = 1;
while (s <= l) {
x.push_back(s);
s *= a;
}
s = 1;
while (s <= l) {
y.push_back(s);
s *= b;
}
set<LL> tmp;
for (auto v: x) {
for (auto u: y) {
if (l % (v * u) == 0) {
tmp.insert(v * u);
}
}
}
cout << tmp.size() << endl;
}
return 0;
}
D.Turtle Tenacity: Continual Mods (思维)
题意:
给一个长度为nnn的数组aaa,询问能否将其打乱得到一个新数组bbb,并满足以下条件:
- b1%b2%b3…bn≠0b_1 \% b_2 \% b_3 \dots b_n \neq 0b1%b2%b3…bn=0
分析:
对每个aia_iai除以aaa数组的gcdgcdgcd,如果数组中的最小值只有111个,那么从最小值开始取模可以满足情况。如果最小值有多个,我们要尝试通过取模操作得到一个比当前最小值更小的数字,如果当前最小值是111,比最小值更小的值是000,输出NO。如果最小值大于111,数组中一定存在一个比它大的数字,用它对最小值取模就可以得到一个更小的数字。
代码:
#include <bits/stdc++.h>
using namespace std;
int a[100005];
int main() {
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
for (int i = 0; i < n; i++) cin >> a[i];
int gcd = a[0];
for (int i = 1; i < n; i++) gcd = __gcd(gcd, a[i]);
for (int i = 0; i < n; i++) a[i] /= gcd;
sort(a, a + n);
if (a[0] != a[1]) {
cout << "YES" << endl;
} else if (a[0] != 1) {
cout << "YES" << endl;
} else cout << "NO" << endl;
}
return 0;
}
E.Turtle vs. Rabbit Race: Optimal Trainings (二分)
题意:
小AAA有 nnn 条跑道可供使用, iii 条跑道由 aia_iai 个等长的部分组成。
给定一个整数 uuu,完成每一段都能使小AAA的能力提高一个特定值,具体描述如下:
- 完成 111 (111-st)部分会使小AAA的成绩提高 uuu 。
- 完成 222(nd)部分会使小AAA的能力提高 u−1u-1u−1 。
- 完成 333-rd 部分会使小AAA的成绩提高 u−2u-2u−2 。
- …\ldots…
- 完成 kkk-th 部分( k≥1k \ge 1k≥1 )会使小AAA的成绩提高 u+1−ku+1-ku+1−k 。 u+1−ku+1-ku+1−k 的值可以是负数,这意味着完成额外的部分会降低小AAA的成绩。
给出一个整数 lll 。询问选择一个整数 rrr ,使 l≤r≤nl \le r \le nl≤r≤n 和小AAA都能完成赛道 l,l+1,…,rl, l + 1, \dots, rl,l+1,…,r 的段。(即总共完成 ∑i=lrai=al+al+1+…+ar\sum\limits_{i=l}^r a_i = a_l + a_{l+1} + \ldots + a_ri=l∑rai=al+al+1+…+ar 节)。
询问所能选择的最佳 rrr ,使得小AAA的成绩最大。如果有相同的rrr输出最小的。
分析:
计算前缀和,二分查找第一个s[r]−s[l−1]>us[r]-s[l-1]>us[r]−s[l−1]>u的位置r1r1r1,以及最后一个s[r]−s[l−1]≤us[r]-s[l-1] \le us[r]−s[l−1]≤u的位置rrr。利用等差数列求和,并将r1,r2r1,r2r1,r2的结果取最大值。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
int a[N], sum[N];
int main() {
int t;
cin >> t;
while (t--) {
int n, q;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
sum[i] = sum[i - 1] + a[i];
}
cin >> q;
while (q--) {
int l, u;
cin >> l >> u;
auto solve = [&](int x) -> LL {
int c = sum[x] - sum[l - 1];
LL res = 1LL * (2 * u + 1 - c) * c / 2;
return res;
};
if (sum[l - 1] + u >= sum[n]) {
cout << n << " ";
continue;
}
if (sum[l - 1] + u < sum[l]) {
cout << l << " ";
continue;
}
int r1 = upper_bound(sum + 1, sum + n + 1, sum[l - 1] + u) - sum;
int r2 = upper_bound(sum + 1, sum + n + 1, sum[l - 1] + u) - sum - 1;
if (solve(r1) > solve(r2))
cout << r1 << " ";
else
cout << r2 << " ";
}
cout << endl;
}
return 0;
}
F.Turtle Mission: Robot and the Earthquake (bfs)
题意:
有一个nnn 行和 mmm 列的网格。单元格状态用aia_iai表示:
- 如果是 ai,j=1a_{i,j} = 1ai,j=1 ,则 (i,j)(i,j)(i,j) 处有一块石头。
- 如果是 ai,j=0a_{i,j} = 0ai,j=0 ,则 (i,j)(i,j)(i,j) 处什么都没有。
由于地震余震的影响,石头跟随构造板块运动:每个石头以每单位时间 111 个单元的速度循环向上移动。从形式上看,如果 (i,j)(i,j)(i,j) 中包含一块岩石,那么它将从 (i,j)(i, j)(i,j) 移动到 (i−1,j)(i - 1, j)(i−1,j) (如果 (i−1,j)(i - 1, j)(i−1,j) 中包含一块岩石,那么它将从 (i,j)(i, j)(i,j) 移动到 (n−1,j)(n - 1, j)(n−1,j) )。
名为 RTRTRT 的机器人最初位于 (0,0)(0,0)(0,0) 。它必须移动到 (n−1,m−1)(n-1,m-1)(n−1,m−1) 处进行地震救援(移动到最右下方的单元格)。地震不会改变机器人的位置,只会改变世界中岩石的位置。
假设 RTRTRT 的当前位置为 (x,y)(x,y)(x,y),它可以进行以下操作:
- 循环向上移动一格,即使用 111 单位时间从 (x,y)(x,y)(x,y) 移动到 ((x+n−1) mod n,y)((x+n-1) \bmod n, y)((x+n−1)modn,y) 。
- 向下循环移动一个单元格,即以 111 为时间单位从 (x,y)(x,y)(x,y) 移动到 ((x+1) mod n,y)((x+1) \bmod n, y)((x+1)modn,y) 。
- 向右移动一格,即使用 111 个时间单位从 (x,y)(x,y)(x,y) 到 (x,y+1)(x, y+1)(x,y+1) 。(只有在 y≤m−1y \le m-1y≤m−1 时,RTRTRT 才能执行此操作)。
注意,RTRTRT 不能使用操作向左移动,也不能停留在某一位置。
求 RTRTRT 到达 (n−1,m−1)(n-1,m-1)(n−1,m−1) 时不与任何岩石相撞所需的最短时间。如果无法做到,输出 −1-1−1 。
分析:
将每次的移动当做表格中的障碍物没有移动,机器人的移动变成:原地不动,向下两步,向右下一步。由于终点也会发生变化,所以先到达最后一列然后再移动到终点的位置最优,先使用BFSBFSBFS计算到达最后一列的最小步数,然后计算最后一列的点与终点的最小距离。
代码:
#include <bits/stdc++.h>
using namespace std;
#define PII pair<int, int>
const int N = 1e3 + 10;
int a[N][N], dist[N][N];
int dir[2][2] = {{2, 0}, {1, 1}};
int main() {
int t;
cin >> t;
while (t--) {
int n, m;
cin >> n >> m;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cin >> a[i][j];
dist[i][j] = 0;
}
}
int end = n - 1;
int ex, ey;
bool flag = 0;
queue<PII > q;
q.push({0, 0});
while (q.size()) {
int cnt = q.size();
while (cnt--) {
int x = q.front().first;
int y = q.front().second;
q.pop();
if (y == m - 1) {
ex = x;
ey = y;
flag = true;
break;
}
for (int i = 0; i < 2; i++) {
int nx = x + dir[i][0];
int ny = y + dir[i][1];
nx = nx % n;
if (nx < 0 || nx >= n || ny < 0 || ny >= m)
continue;
if (i == 0 && (a[(x + 1) % n][y] == 1 || a[(x + 2) % n][y] == 1))
continue;
if (i == 1 && (a[(x + 1) % n][y + 1] == 1))
continue;
if (dist[nx][ny])
continue;
q.push({nx, ny});
dist[nx][ny] = dist[x][y] + 1;
}
}
if (flag)
break;
end++;
}
if (flag == 0) {
cout << -1 << endl;
} else {
end = end % n;
cout << dist[ex][ey] + min(abs(end - ex), (n - abs(end - ex)) % n) << endl;
}
}
return 0;
}
G.Turtle Magic: Royal Turtle Shell Pattern (打表)
题意:
给一个n×mn \times mn×m的网格,最初,整个网格是空的。进行 qqq 次操作。 iii次操作如下:指定当前空单元格 (ri,ci)(r_i,c_i)(ri,ci) 和一个形状(圆形或方形),然后在单元格 (ri,ci)(r_i,c_i)(ri,ci) 中放入一个指定形状的幸运饼干。在进行 iii 操作后,单元格 (ri,ci)(r_i,c_i)(ri,ci) 不再为空。
在每次操作之前,以及所有操作结束之后,询问在所有剩余的空单元格中放置幸运饼干的方法有多少种,从而满足以下条件:
没有三个连续的单元格(水平方向、垂直方向和对角线方向)包含相同形状的饼干。形式上
- 不存在满足 1≤i≤n,1≤j≤m−21 \le i \le n, 1 \le j \le m-21≤i≤n,1≤j≤m−2 条件的 (i,j)(i,j)(i,j) ,即 (i,j),(i,j+1),(i,j+2)(i,j), (i,j+1), (i,j+2)(i,j),(i,j+1),(i,j+2) 单元格中有相同形状的饼干。
- 不存在满足 1≤i≤n−2,1≤j≤m1 \le i \le n-2, 1 \le j \le m1≤i≤n−2,1≤j≤m 条件的 (i,j)(i,j)(i,j) ,即 (i,j),(i+1,j),(i+2,j)(i,j), (i+1,j), (i+2,j)(i,j),(i+1,j),(i+2,j) 单元格中存在形状相同的饼干。
- 不存在满足 1≤i≤n−2,1≤j≤m−21 \le i \le n-2, 1 \le j \le m-21≤i≤n−2,1≤j≤m−2 条件的 (i,j)(i,j)(i,j) ,即 (i,j),(i+1,j+1),(i+2,j+2)(i,j), (i+1,j+1), (i+2,j+2)(i,j),(i+1,j+1),(i+2,j+2) 单元格中有形状相同的饼干。
- 不存在满足 1≤i≤n−2,1≤j≤m−21 \le i \le n-2, 1 \le j \le m-21≤i≤n−2,1≤j≤m−2 条件的 (i,j)(i,j)(i,j) ,即 (i,j+2),(i+1,j+1),(i+2,j)(i,j+2), (i+1,j+1), (i+2,j)(i,j+2),(i+1,j+1),(i+2,j) 单元格中有形状相同的饼干。
将答案对998244353998244353998244353取模。
分析:
通过打表发现n,m≥5n,m \ge 5n,m≥5的情况只有888种,并且满足要么每行都是两个两个交错,要么每列都是两个两个交错。那么合法方案只需要考虑以下因素:
-
行还是列为两个两个交错的情况
-
第一行/列第一个格子是什么
-
第一行/列第二个格子是什么
每次新加入的点只需要判断是否会使原来的情况不合法即可。
代码:
#include <bits/stdc++.h>
using namespace std;
int main() {
int t;
cin >> t;
while (t--) {
int n, m, q;
cin >> n >> m >> q;
cout << 8 << endl;
int ans[8]{};
while (q--) {
int x, y;
string s;
cin >> x >> y >> s;
int op = (s[0] == 'c');
for (int i = 0; i < 8; i++) {
int tmp1 = (i >> 0) & 1;
int tmp2 = (i >> 1) & 1;
int tmp3 = (i >> 2) & 1;
if (tmp1 == 0) {
int t = y % 2;
int tmp = op;
if (x % 2 != 0)
tmp ^= 1;
if (y % 4 > 1)
tmp ^= 1;
if (t == 0 && tmp2 != tmp) {
ans[i] = 1;
}
if (t == 1 && tmp3 != tmp) {
ans[i] = 1;
}
} else {
int t = x % 2;
int tmp = op;
if (y % 2 != 0)
tmp ^= 1;
if (x % 4 > 1)
tmp ^= 1;
if (t == 0 && tmp2 != tmp) {
ans[i] = 1;
}
if (t == 1 && tmp3 != tmp) {
ans[i] = 1;
}
}
}
int sum = 0;
for (int i = 0; i < 8; i++)
if (ans[i] == 0)
sum++;
cout << sum << endl;
}
}
return 0;
}
赛后交流
在比赛结束后,会在交流群中给出比赛题解,同学们可以在赛后查看题解进行补题。
群号: 704572101,赛后大家可以一起交流做题思路,分享做题技巧,欢迎大家的加入。

1726

被折叠的 条评论
为什么被折叠?



