2023 年度安徽中医药大学 ACM 校内选拔赛题解
![Yestercafe](/assets/images/avatars/ivan_chien.png)
Written
by
Yestercafe
with
Ereflect,
on
Ivan_Chien
C++
A - Roxy Tree
跟完全二叉树一样的求。
#include <iostream>
#include <map>
#include <limits>
#include <algorithm>
using i64 = long long;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::map<i64, i64> width;
i64 s = 0LL;
for (i64 p = 1, v = 1; s < std::numeric_limits<i64>::max() / 10; ++p) {
s += width[p] = v;
if (p & 1) v *= 2;
else v *= 3;
}
i64 t;
while (std::cin >> t) {
i64 sum = 0LL;
auto fnd = std::find_if(width.begin(), width.end(), [t, &sum] (auto x) mutable { return t < (sum += x.second); });
auto [p, v] = *fnd;
std::cout << p << ' ' << t - (sum - v) + 1 << std::endl;
}
return 0;
}
B - Variable-like String Literal Check
英文签到。
#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>
using i64 = long long;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int tt;
std::cin >> tt;
while (tt--) {
std::string s;
std::cin >> s;
if (!isalpha(s[0]) && s[0] != '_') {
std::cout << "No" << std::endl;
continue;
}
if (!std::all_of(s.begin() + 1, s.end(), [](char x) { return isalnum(x) || x == '_'; })) {
std::cout << "No" << std::endl;
continue;
}
std::cout << "Yes" << std::endl;
}
return 0;
}
C - Push-pop-push-pop
模拟。
#include <iostream>
#include <deque>
using i64 = long long;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int q;
std::cin >> q;
std::deque<int> dq;
while (q--) {
char instruction;
std::cin >> instruction;
int operand;
switch (instruction) {
case 's':
case 'q':
std::cin >> operand;
dq.push_back(operand);
break;
case 'S':
if (!dq.empty()) {
dq.pop_back();
}
break;
case 'Q':
if (!dq.empty()) {
dq.pop_front();
}
break;
case 'd':
if (dq.empty()) {
std::cout << "empty" << std::endl;
} else {
int n = dq.size();
for (int i = 0; i < n; ++i) {
std::cout << dq[i] << ",\n"[i == n - 1];
}
}
break;
default:
break;
}
}
return 0;
}
D - Balanced Roxy Substring
不能算区间 DP 的区间 DP,可以说是记忆化。亦可用滑动窗口。
#include <iostream>
#include <string>
#include <array>
#include <vector>
using i64 = long long;
void update(std::array<int, 2>&, const char);
bool check(const std::array<int, 2>&);
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::string s;
std::cin >> s;
int n = s.length();
int ans = 0;
std::vector<std::array<int, 2>> prev(n), f(n);
for (int i = 0; i + 1 < n; ++i) {
update(prev[i], s[i]);
update(prev[i], s[i + 1]);
if (check(prev[i])) {
ans = 2;
}
}
for (int d = 2; d < n; ++d) {
for (int i = 0; i + d < n; ++i) {
f[i] = prev[i];
update(f[i], s[i + d]);
if (d & 1) {
if (check(f[i])) {
ans = 1 + d;
}
}
}
f.swap(prev);
}
std::cout << ans << std::endl;
return 0;
}
void update(std::array<int, 2>& a, const char c) {
switch (c) {
case 'r': ++a[0]; break;
case 'o': --a[0]; break;
case 'x': ++a[1]; break;
case 'y': --a[1]; break;
}
}
bool check(const std::array<int, 2>& a) {
return !a[0] && !a[1];
}
E - Xepa Predator
结构体排序。
#include <iostream>
#include <vector>
#include <algorithm>
using i64 = long long;
struct Student {
int id;
int p, s;
Student() = default;
Student(int id, int p, int s) : id{id}, p{p}, s{s} {}
};
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
constexpr int N = 60;
std::vector<Student> v(N);
int my_id;
std::cin >> my_id;
for (int i = 0; i < N; ++i) std::cin >> v[i].id;
for (int i = 0; i < N; ++i) std::cin >> v[i].p;
for (int i = 0; i < N; ++i) std::cin >> v[i].s;
std::sort(v.begin(), v.end(), [](const Student& a, const Student& b) {
auto af = 2 * a.p + 1 * a.s;
auto bf = 2 * b.p + 1 * b.s;
if (af != bf)
return af > bf;
else if (a.p != b.p)
return a.p > b.p;
else if (a.s != b.s)
return a.s > b.s;
return a.id < b.id;
});
auto fnd = std::find_if(v.begin(), v.end(), [my_id](const Student& s) { return s.id == my_id; });
if (fnd == v.begin()) {
std::cout << "Xepa Champion" << std::endl;
} else {
std::cout << fnd - v.begin() + 1 << std::endl;
}
return 0;
}
F - 水王级魔法师
签到。
#include <iostream>
#include <unordered_map>
#include <limits>
#include <cassert>
using i64 = long long;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::unordered_map<int, i64> t;
for (i64 i = 1, v = 2LL; v < i64(std::numeric_limits<int>::max()); ++i, v *= 2) {
t[i] = v - 1LL;
}
int n;
std::cin >> n;
int ans = 0;
while (n--) {
int i;
std::cin >> i;
ans += static_cast<int>(t[i]);
assert(ans >= 0);
}
std::cout << ans << std::endl;
return 0;
}
G - 鸭鸭杯
暴力即可。
#include <iostream>
#include <numeric>
using i64 = long long;
constexpr auto inf = 0x3f3f3f3f;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int t;
std::cin >> t;
while (t--) {
int g, l, m;
std::cin >> g >> l >> m;
if (g < l) std::swap(g, l);
if (g == l) {
if (m % g == 0) {
std::cout << m / g << std::endl;
} else {
std::cout << -1 << std::endl;
}
continue;
}
int ans = inf;
for (int f = m / g + 1; f >= 0; --f) {
auto remain = m - f * g;
if (remain < 0) continue;
if (remain % l == 0) {
ans = f + remain / l;
break;
}
}
std::cout << (ans == inf ? -1 : ans) << std::endl;
}
return 0;
}
H - 龙族的传送魔法
BFS 模板。
#include <iostream>
#include <queue>
#include <deque>
#include <utility>
#include <map>
using i64 = long long;
constexpr int dir[][2] = {1, 0, -1, 0, 0, 1, 0, -1};
int operator-(std::pair<int, int> b, std::pair<int, int> a) {
return (b.first - a.first) + (b.second - a.second);
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int w, h;
std::cin >> w >> h;
std::pair<int, int> start, end;
std::cin >> start.first >> start.second >> end.first >> end.second;
int cnt_portal;
std::cin >> cnt_portal;
std::map<std::pair<int, int>, std::pair<int, int>> portals;
while (cnt_portal--) {
int sx, sy, ex, ey;
std::cin >> sx >> sy >> ex >> ey;
portals[std::make_pair(sx, sy)] = std::make_pair(ex, ey);
}
std::vector vis(w, std::vector(h, false));
std::deque<std::pair<int, int>> q;
vis[start.first][start.second] = true;
q.push_back(start);
int depth = 0;
bool is_reached = false;
while (!q.empty()) {
int s = q.size();
while (s--) {
auto fr = q.front();
q.pop_front();
if (fr == end) {
is_reached = true;
break;
}
for (int d = 0; d < 4; ++d) {
int nxt_x = fr.first + dir[d][0], nxt_y = fr.second + dir[d][1];
if (nxt_x < 0 || nxt_x >= w || nxt_y < 0 || nxt_y >= h || vis[nxt_x][nxt_y])
continue;
vis[nxt_x][nxt_y] = true;
q.push_back({nxt_x, nxt_y});
}
if (auto fnd = portals.find(fr); fnd != portals.end()) {
vis[fnd->second.first][fnd->second.second] = true;
q.push_back(fnd->second);
}
}
if (is_reached) break;
++depth;
}
std::cout << (end - start) - depth << std::endl;
return 0;
}
i - 黄金律法之谜
背包 DP。
#include <iostream>
#include <unordered_map>
#include <vector>
#include <limits>
using i64 = long long;
constexpr auto inf = std::numeric_limits<int>::max();
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int r, n;
std::cin >> r >> n;
std::unordered_map<int, int> cnt_map;
while (n--) {
int cnt_rune, val_rune;
std::cin >> cnt_rune >> val_rune;
cnt_map[val_rune] += cnt_rune;
}
std::vector cnt(cnt_map.begin(), cnt_map.end());
n = cnt.size();
std::vector f(n + 1, std::vector(r + 1, 0));
for (int i_rune = 1; i_rune <= n; ++i_rune) {
for (int i_r = 1; i_r <= r; ++i_r) {
f[i_rune][i_r] = inf;
int rune_val = cnt[i_rune - 1].first;
for (int c = 0; c <= cnt[i_rune - 1].second; ++c) {
int i_rd = std::max(0, i_r - rune_val * c);
if (f[i_rune - 1][i_rd] == inf) continue;
int acc = f[i_rune - 1][i_rd] + rune_val * c;
if (acc >= i_r) {
f[i_rune][i_r] = std::min(f[i_rune][i_r], acc);
}
}
}
}
std::cout << (f[n][r] == inf ? -1 : f[n][r]) << std::endl;
return 0;
}
J - 开放世界
单源最短路模板。
#include <iostream>
#include <vector>
#include <limits>
using i64 = long long;
constexpr i64 inf = 0x3f3f3f3f3f3f3f3fLL;
// https://oi-wiki.org/graph/shortest-path/#dijkstra-%E7%AE%97%E6%B3%95
struct edge {
i64 v, w;
};
std::vector<std::vector<edge>> e;
std::vector<i64> dis, vis;
void dijkstra(int n, int s) {
dis[s] = 0;
for (int i = 1; i <= n; i++) {
i64 u = 0, mind = inf;
for (int j = 1; j <= n; j++)
if (!vis[j] && dis[j] < mind) u = j, mind = dis[j];
vis[u] = true;
for (auto ed : e[u]) {
i64 v = ed.v, w = ed.w;
if (dis[v] > dis[u] + w) dis[v] = dis[u] + w;
}
}
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n, q;
std::cin >> n >> q;
e.resize(n + 1);
dis.resize(n + 1, std::numeric_limits<i64>::max());
vis.resize(n + 1);
for (int i = 0; i < q; ++i) {
int a, b, d;
std::cin >> a >> b >> d;
e[a].push_back({1LL * b, 1LL * d});
e[b].push_back({1LL * a, 1LL * d});
}
dijkstra(n, 1);
std::cout << (dis[n] == std::numeric_limits<i64>::max() ? -1 : dis[n]) << std::endl;
return 0;
}
K - 画家算法
二维差分、前缀和。
#include <iostream>
#include <vector>
using i64 = long long;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int w, h, n;
std::cin >> w >> h >> n;
std::vector diff(w + 2, std::vector(h + 2, 0));
for (int i = 0; i < n; ++i) {
int x1, y1, x2, y2;
std::cin >> x1 >> y1 >> x2 >> y2;
++x1, ++y1, ++x2, ++y2;
++diff[x1][y1];
--diff[x1][y2 + 1];
--diff[x2 + 1][y1];
++diff[x2 + 1][y2 + 1];
}
for (int i = 1; i <= w; ++i) {
for (int j = 1; j <= h; ++j) {
diff[i][j] += diff[i - 1][j] + diff[i][j - 1] - diff[i - 1][j - 1];
}
}
std::vector pref(w + 1, std::vector(h + 1, 0));
for (int i = 1; i <= w; ++i) {
for (int j = 1; j <= h; ++j) {
pref[i][j] = diff[i][j] + pref[i - 1][j] + pref[i][j - 1] - pref[i - 1][j - 1];
}
}
int q;
std::cin >> q;
while (q--) {
int x1, y1, x2, y2;
std::cin >> x1 >> y1 >> x2 >> y2;
++x2, ++y2;
std::cout << pref[x2][y2] - pref[x1][y2] - pref[x2][y1] + pref[x1][y1] << std::endl;
}
return 0;
}
L - 本次比赛的白给题
读题题。模拟。
#include <iostream>
#include <string>
#include <vector>
#include <unordered_set>
#include <algorithm>
#include <set>
#include <cctype>
using i64 = long long;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::string token;
std::vector<std::unordered_set<std::string>> params;
std::vector<std::set<std::string>> vars;
while (std::cin >> token) {
if (token == "#") {
params.push_back({});
vars.push_back({});
while (std::cin >> token) {
if (token == ":") break;
params.back().insert(token);
}
} else if (std::all_of(token.begin(), token.end(), islower)) {
if (params.back().find(token) == params.back().end()) {
vars.back().insert(token);
}
}
}
int n = vars.size();
for (int i = 0; i < n; ++i) {
std::cout << i + 1;
for (auto var : vars[i]) {
std::cout << ' ' << var;
}
std::cout << std::endl;
}
return 0;
}
Python
A
width = [0]
s = 0
UPPER_BOUND = 1 << 63
v = 1
while s <= UPPER_BOUND:
width.append(v)
s += v
if len(width) % 2 == 0:
v *= 2
else:
v *= 3
while True:
try:
n = int(input())
s = 0
for i, e in enumerate(width):
s += e
if n < s:
break
print(i, n - (s - width[i]) + 1)
except EOFError:
break
B
n = int(input())
for _ in range(n):
var = input()
if not (var[0].isalpha() or var[0] == '_'):
print("No")
continue
if any([not (c.isalnum() or c == '_') for c in var]):
print("No")
continue
print("Yes")
C
n = int(input())
seq = []
def print_seq(seq):
if len(seq) == 0:
print('empty')
return
print(','.join(seq))
for _ in range(n):
instr = input().split()
if instr[0] == 'q' or instr[0] == 's':
seq.append(str(int(instr[1])))
elif instr[0] == 'd':
print_seq(seq)
elif instr[0] == 'Q':
if len(seq) != 0:
seq.pop(0)
elif instr[0] == 'S':
if len(seq) != 0:
seq.pop()
D
s = input()
n = len(s)
REV = {'r': 'o', 'o': 'r', 'x': 'y', 'y': 'x'}
cnt = [0, 0]
def update(c):
global cnt
if c == 'r':
cnt[0] += 1
elif c == 'o':
cnt[0] -= 1
elif c == 'x':
cnt[1] += 1
elif c == 'y':
cnt[1] -= 1
def check():
return cnt[0] == 0 and cnt[1] == 0
ans = 0
for d in range(2, n):
cnt = [0, 0]
for i in range(d):
update(s[i])
if check():
ans = d
continue
for i in range(d, n):
update(REV[s[i - d]])
update(s[i])
if check():
ans = d
break
print(ans)
E
my_id = int(input())
ids = list(map(int, input().split()))
pps = list(map(int, input().split()))
sps = list(map(int, input().split()))
class Player:
def __init__(self, pid, pp, sp):
self.pid = pid
self.pp = pp
self.sp = sp
self.rp = 2 * pp + 1 * sp
players = []
for i in range(len(ids)):
players.append(Player(ids[i], pps[i], sps[i]))
players.sort(key=lambda p : (-p.rp, -p.pp, -p.sp, p.pid))
for i, player in enumerate(players):
if player.pid == my_id:
if i == 0:
print("Xepa Champion")
else:
print(i + 1)
F
m = [0]
s = 2
UPPER_BOUND = 1 << 32
while s <= UPPER_BOUND:
m.append(s - 1)
s *= 2
n = int(input())
ans = 0
for _ in range(n):
t = int(input())
ans += m[t]
print(ans)
G
from math import inf
t = int(input())
for _ in range(t):
a, b, m = list(map(int, input().split()))
if a < b:
a, b = b, a
elif a == b:
if m % a == 0:
print(m // a)
else:
print(-1)
continue
ans = inf
for f in range(m // a + 1, -1, -1):
remain = m - f * a
if remain < 0: continue
if remain % b == 0:
ans = f + remain // b
break
print(ans if ans != inf else -1)
H
w, h, ax, ay, bx, by = list(map(int, input().split()))
t = int(input())
portals = dict()
for _ in range(t):
x1, y1, x2, y2 = list(map(int, input().split()))
portals[(x1, y1)] = (x2, y2)
DIR = [(1, 0), (-1, 0), (0, 1), (0, -1)]
q = []
q.append((ax, ay))
vis = [[False] * h for _ in range(w)]
vis[ax][ay] = True
depth = 0
is_reached = False
while len(q) != 0:
s = len(q)
for _ in range(s):
curr = q[0]
q.pop(0)
if curr[0] == bx and curr[1] == by:
is_reached = True
break
for d in DIR:
nxt_x, nxt_y = curr[0] + d[0], curr[1] + d[1]
if nxt_x < 0 or nxt_x >= w or nxt_y < 0 or nxt_y >= h or vis[nxt_x][nxt_y]:
continue
vis[nxt_x][nxt_y] = True
q.append((nxt_x, nxt_y))
if curr in portals:
dest = portals[curr]
q.append(dest)
vis[dest[0]][dest[1]] = True
if is_reached: break
depth += 1
print(abs(ax - bx) + abs(ay - by) - depth)
L
tokens = input().split()
func_env = []
captured = []
is_parsing_params = False
for token in tokens:
if is_parsing_params:
if token == ":":
is_parsing_params = False
continue
func_env[-1].add(token)
if token == "#":
func_env.append(set())
captured.append(set())
is_parsing_params = True
continue
elif all([c.isalpha() for c in token]):
if not token in func_env[-1]:
captured[-1].add(token)
for i, c in enumerate(captured):
print(i + 1, end='')
c = sorted(list(c))
for name in c:
print(' ' + name, end='')
print()
Ereflect
Python
B
def check_string(s):
digits = [str(x) for x in range(10)]
chars = [chr(x) for x in range(95) if x != 32]
if s[0] in digits:
return 'No'
if any(c not in set(chars + digits) for c in s):
return 'No'
return 'Yes'
n = int(input())
for _ in range(n):
s = input().strip()
ans = check_string(s)
print(ans)
C
def list_operation(commands):
l = []
for cmd in commands:
if cmd[0] == 'q' or cmd[0] == 's':
l.append(int(cmd[1]))
elif cmd[0] == 'S' and l:
l.pop()
elif cmd[0] == 'Q' and l:
l = l[1:]
elif cmd[0] == 'd':
if not l:
print("empty")
continue
print(','.join(str(i) for i in l))
return l
n = int(input())
commands = [input().split() for _ in range(n)]
list_operation(commands)
F
n = int(input())
l = [int(input()) for _ in range(n)]
maxx = max(l)
mapl = [2 ** (i - 1) for i in range(1, maxx + 2)]
mapl[1:] = [mapl[i - 1] + mapl[i] for i in range(1, maxx + 1)]
ans = sum(mapl[i - 1] for i in l)
print(ans)
Comments