A. Turtle Puzzle: Rearrange and Negate
因为可以任意排列这个数组,并将一段区间内的数乘 $-1$,我们可以排序后把所有负数变为正数,即可
$code:$
void solve() {
int n;
std::cin >> n;
int ans = 0;
for(int i = 0, x; i < n; i ++ ) {
std::cin >> x;
ans += std::abs(x);
}
std::cout << ans << '\n';
}
B. Turtle Math: Fast Three Task
分类讨论,$\sum_{i=1}^na_i\mod 3$ 等于 $0$ 的话不需要操作,等于 $1$ 就看有没有 $\mod 3 \equiv 1$ 的数,有得话删掉,没有的话就对一个数 $+2$ 即可,等于 $2$ 的话直接对一个数 $+1$ 即可
void solve() {
int n;
std::cin >> n;
std::array<int, 3> cnt{};
for(int i = 0; i < n; i ++ ) {
int x;
std::cin >> x;
cnt[x % 3] ++;
}
int o = (cnt[1] + 2 * cnt[2]) % 3;
if(o == 0) {
std::cout << 0 << '\n';
} else if(o == 1) {
if(cnt[1]) {
std::cout << 1 << '\n';
} else {
std::cout << 2 << '\n';
}
} else {
std::cout << 1 << '\n';
}
}
C. Turtle Fingers: Count the Values of k
观察到 $x, y$ 的范围不会很大于是乎我们枚举 $x, y$ 然后统计 $k$ 的种类数即可
void solve() {
int a, b, l;
std::cin >> a >> b >> l;
std::set<int> S;
for(int i = 1; i <= l; i *= a) {
for(int j = 1; j <= l; j *= b) {
if(1LL * i * j <= l) {
if(l % (i * j) == 0) {
S.insert(l / (i * j));
}
}
}
}
std::cout << S.size() << '\n';
}
D. Turtle Tenacity: Continual Mods
暂时不会证明,有排序讨论的做法,我的写法是判断整个数组的 $gcd$ 出现了多少次,不超过 $1$ 次即可
void solve() {
int n;
std::cin >> n;
int g = 0;
std::vector<int> a(n);
for(int i = 0; i < n; i ++ ) {
std::cin >> a[i];
g = std::gcd(g, a[i]);
}
int cnt = 0;
for(int i = 0; i < n; i ++ ) {
if(g == a[i]) {
cnt ++;
}
}
std::cout << (cnt > 1 ? "NO" : "YES") << '\n';
}
E. Turtle vs. Rabbit Race: Optimal Trainings
我们找到总 $l$ 出发然后场数 $\ge u$ 的位置,之后的数全是负数不可取,然后当前位置也有可能包含负数,我们与前一个位置比较一下大小即可得到答案,找到这个位置可以用前缀和+二分来求
void solve() {
int n;
std::cin >> n;
std::vector<i64> a(n + 1);
for(int i = 1; i <= n; i ++ ) {
std::cin >> a[i];
a[i] += a[i - 1];
}
auto get = [&](int l, int r, int u) -> i64 {
i64 n = a[r] - a[l - 1];
return 1LL * u * n - 1LL * (n - 1) * n / 2;
};
auto fid = [&](int l, int v) -> int {
int r = n;
while(l < r) {
int mid = l + r >> 1;
if(a[mid] >= v) r = mid;
else l = mid + 1;
}
return r;
};
int q;
std::cin >> q;
while(q -- ) {
int l, u;
std::cin >> l >> u;
int p = fid(l, a[l - 1] + u + 1);
// int p = std::lower_bound(a.begin() + l, a.end(), a[l - 1] + u + 1) - a.begin();
if(p == l) {
std::cout << l << ' ';
} else {
i64 v1 = get(l, p, u), v2 = get(l, p - 1, u);
std::cout << (v1 > v2 ? p : p - 1) << ' ';
}
}
std::cout << '\n';
}
F. Turtle Mission: Robot and the Earthquake
我们可以将地图的运动转换为人物的相对运动,于是就得到了三种运动方式 $(x,y),(x+2,y),(x+1,y+1)$ ,然后观察到答案也会相对运动每次运动 $(x+1,y)$ ,答案可以在边界上移动,我们只要能达到右边界,然后停在原地等答案到即可,先 $bfs$ 求出到边界的最短路,然后加上需要等待答案过来的时间即可
int n, m;
std::cin >> n >> m;
std::vector<std::vector<int>> g(n, std::vector<int>(m));
for(int i = 0; i < n; i ++ ) {
for(int j = 0; j < m; j ++ ) {
std::cin >> g[i][j];
}
}
std::vector<std::vector<int>> d(n, std::vector<int>(m, -1));
std::queue<std::pair<int, int>> q;
q.push({0, 0});
d[0][0] = 0;
auto ok = [&](int x, int y) -> bool {
return !g[x][y];
};
while(!q.empty()) {
auto [x, y] = q.front(); q.pop();
if(ok((x + 1) % n, y) && ok((x + 2) % n, y) && d[(x + 2) % n][y] == -1) {
d[(x + 2) % n][y] = d[x][y] + 1;
q.push({(x + 2) % n, y});
}
if(ok((x + 1) % n, (y + 1) % m) && d[(x + 1) % n][(y + 1) % m] == -1) {
d[(x + 1) % n][(y + 1) % m] = d[x][y] + 1;
q.push({(x + 1) % n, (y + 1) % m});
}
}
int ans = 1e9;
for(int i = 0; i < n; i ++ ) {
if(d[i][m - 1] != -1) {
int x = d[i][m - 1] % n, y = (i + 1) % n;
ans = std::min(ans, d[i][m - 1] + (y - x + n) % n);
}
}
std::cout << (ans == 1e9 ? -1 : ans) << '\n';
}