UNIQUE VISION Programming Contest 2025 Spring (AtCoder Beginner Contest 398)
A - Doors in the Center
分奇偶讨论
点击查看代码
void solve() {
int n;
std::cin >> n;
if (n & 1) {
std::string s = std::string(n / 2, '-') + "=" + std::string(n / 2, '-');
std::cout << s << "\n";
} else {
std::string s = std::string(n / 2 - 1, '-') + "=";
std::string ans = s;
std::reverse(s.begin(), s.end());
ans += s;
std::cout << ans << "\n";
}
}
B - Full House 3
判断出现次数最多的两个数是否满足条件。
点击查看代码
void solve() {
int cnt[14]{};
for (int i = 0; i < 7; ++ i) {
int x;
std::cin >> x;
++ cnt[x];
}
std::sort(cnt, cnt + 14, std::greater<int>());
if (cnt[0] >= 3 && cnt[1] >= 2) {
std::cout << "Yes\n";
} else {
std::cout << "No\n";
}
}
C - Uniqueness
题意:找一个位置它是唯一出现过的数里值最大的。
点击查看代码
void solve() {
int n;
std::cin >> n;
std::vector<int> a(n);
std::map<int, int> mp;
for (int i = 0; i < n; ++ i) {
std::cin >> a[i];
++ mp[a[i]];
}
int ans = -1;
for (int i = n - 1; i >= 0; -- i) {
if (mp[a[i]] == 1) {
if (ans == -1 || a[i] > a[ans - 1]) {
ans = i + 1;
}
}
}
std::cout << ans << "\n";
}
D - Bonfire
题意:\((0, 0)\)处不断生成烟,每秒所有烟都会按照给出的序列移动,烟不会消失。求每个时刻\((r, c)\)这个位置有没有烟。
如果第\(i\)时刻有一团烟在\((r, c)\),那么就是有一个\([j, i]\)使得操作这个区间可以到\((r, c)\),那么用\(set\)存坐标的变化,如果当前坐标是\((x, y)\),判断有没有一个坐标是\((x - r, y - c)\)。
点击查看代码
void solve() {
int n, r, c;
std::cin >> n >> r >> c;
std::string s;
std::cin >> s;
std::set<std::pair<int, int>> set;
int x = 0, y = 0;
set.insert({x, y});
std::string ans(n, '0');
for (int i = 0; i < n; ++ i) {
if (s[i] == 'N') {
-- x;
} else if (s[i] == 'W') {
-- y;
} else if (s[i] == 'S') {
++ x;
} else {
++ y;
}
if (set.count({x - r, y - c})) {
ans[i] = '1';
}
set.insert({x, y});
}
std::cout << ans << "\n";
}
E - Tree Game
题意:交互题。给出一棵树,你和别人轮流加边,加边的规则是,这个边之前没有出现过,且加上这条边之后没有奇数环出现。你可以选择是先手还是后手。
每次都只能给距离是偶数的点连边。
那么把所有距离是偶数的点存下来,根据奇偶判断先手。
点击查看代码
std::pair<int, int> ask() {
int u, v;
std::cin >> u >> v;
return {u, v};
}
void solve() {
int n;
std::cin >> n;
std::vector<std::vector<int>> adj(n);
for (int i = 1; i < n; ++ i) {
int u, v;
std::cin >> u >> v;
-- u, -- v;
adj[u].push_back(v);
adj[v].push_back(u);
}
std::vector d(n, std::vector<int>(n));
for (int i = 0; i < n; ++ i) {
auto dfs = [&](auto & self, int u) -> void {
for (auto & v : adj[u]) {
if (d[i][v] == 0) {
d[i][v] = d[i][u] + 1;
self(self, v);
}
}
};
d[i][i] = 1;
dfs(dfs, i);
}
std::set<std::pair<int, int>> s;
for (int i = 0; i < n; ++ i) {
for (int j = i + 1; j < n; ++ j) {
if (d[i][j] % 2 == 0) {
s.insert({i, j});
}
}
}
for (int i = 0; i < n; ++ i) {
for (auto & v : adj[i]) {
s.erase({i, v});
}
}
if (s.size() % 2 == 1) {
std::cout << "First" << std::endl;
} else {
std::cout << "Second" << std::endl;
auto [u, v] = ask();F - ABCBA
if (u == -1) {
return;
}
if (u > v) {
std::swap(u, v);
}
-- u, -- v;
s.erase({u, v});
}
while (s.size()) {
std::cout << s.begin()->first + 1 << " " << s.begin()->second + 1 << std::endl;
s.erase(s.begin());
auto [u, v] = ask();
if (u == -1) {
return;
}
if (u > v) {
std::swap(u, v);
}
-- u, -- v;
s.erase({u, v});
}
}
F - ABCBA
题意:找一个字符串,使得\(s\)是它的前缀,且这个字符串是回文,并且要求长度尽可能小。
我们要求最长的是回文的后缀,这个可以用\(hash\)。
点击查看代码
void solve() {
std::string s;
std::cin >> s;
int n = s.size();
std::vector<ui64> h(n + 1), rh(n + 1), p(n + 1);
for (int i = 0; i < n; ++ i) {
h[i + 1] = (131 * h[i] + s[i] - 'A');
}
for (int i = 0; i < n; ++ i) {
rh[i + 1] = (131 * rh[i] + s[n - 1 - i] - 'A');
}
p[0] = 1;
for (int i = 0; i < n; ++ i) {
p[i + 1] = 131 * p[i];
}
auto get = [&](std::vector<ui64> & h, int l, int r) -> ui64{
return (h[r] - h[l] * p[r - l]);
};
int pos = n;
for (int i = n; i >= 1; -- i) {
if (get(h, n - i + 1, n) == get(rh, 1, i)) {
pos = n - i;
break;
}
}
std::string ans = s.substr(0, pos);
std::reverse(ans.begin(), ans.end());
ans = s.substr(0, pos) + s.substr(pos) + ans;
std::cout << ans << "\n";
}