个人题解仅供参考。
A
签到。
C++ Code
#include "bits/stdc++.h"
using namespace std;
using i64 = long long;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<vector<char>> a(2 * n + 1, vector<char>(2 * n + 1, '.'));
for (int i = 2 * n; i > n; i--) {
a[i][0] = '@';
a[i][2 * n] = '@';
}
for (int i = 0; i <= 2 * n; i++) {
a[n][i] = '@';
}
for (int i = 0; i <= n; i++) {
a[i][i + n] = '@';
}
for (int i = n; i >= 0; i--) {
a[i][n - i] = '@';
}
for (int i = 0; i <= 2 * n; i++) {
for (int j = 0; j <= 2 * n; j++) {
cout << a[i][j];
}
cout << '\n';
}
return 0;
}
C
一个数要么分给惠惠,要么分给悠悠,直接 dfs 就行。
C++ Code
#include "bits/stdc++.h"
using namespace std;
using i64 = long long;
void solve() {
int n;
cin >> n;
vector<int> a(n);
for (int i = 0; i < n; i++) {
cin >> a[i];
}
if (n % 2 == 1) {
cout << "Yunyun\n";
return;
}
vector<int> p, q;
bool ok = 0;
function<void(int)> dfs = [&](int I) {
if (ok) {
return;
}
int len1 = p.size(), len2 = q.size();
for (int i = 0; i < min(len1, len2); i++) {
if (p[i] != q[i]) {
return;
}
}
if (len1 == n / 2 && len2 == n / 2) {
ok = 1;
return;
}
if (I == n) {
return;
}
if (len1 > n / 2) {
return;
}
if (len2 > n / 2) {
return;
}
p.push_back(a[I]);
dfs(I + 1);
p.pop_back();
q.push_back(a[I]);
dfs(I + 1);
q.pop_back();
};
p.push_back(a[0]);
dfs(1);
cout << (ok ? "Megumin" : "Yunyun") << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}
E
这里使用字符串哈希。显然此题还有其他别的方法。
前后一样的消掉,然后枚举翻转点,两种情况,翻转前面或者翻转后面。数据 ,单哈希可能会哈希碰撞。时间复杂度 。
与此题类似:https://atcoder.jp/contests/abc284/tasks/abc284_f
赛后发现此题来自:https://codeforces.com/gym/104095/problem/K
C++ Code
#include "bits/stdc++.h"
using namespace std;
using i64 = long long;
constexpr int B = 777;
constexpr i64 P = 100000000000031;
i64 *p;
void init(int N) {
p = new i64 [N + 1];
p[0] = 1;
for (int i = 1; i <= N; i++) {
p[i] = p[i - 1] * B % P;
}
}
struct StringHash {
vector<i64> h;
StringHash() : h(1) {}
void push_back(char ch) {
h.push_back((h.back() * B + ch) % P);
}
i64 get(int l, int r) {
return (h[r] + __int128(h[l]) * (P - p[r - l])) % P;
}
};
void solve() {
string s;
cin >> s;
int n = s.size();
deque<char> q;
for (int i = 0; i < n; i++) {
q.push_back(s[i]);
}
while (q.size() > 1 && q.front() == q.back()) {
q.pop_back();
q.pop_front();
}
if (q.size() < 2) {
cout << "Yes\n";
return;
}
StringHash hs, hs1;
int m = q.size();
for (int i = 0; i < m; i++) {
hs.push_back(q[i]);
}
for (int i = m - 1; i >= 0; i--) {
hs1.push_back(q[i]);
}
auto work = [&](StringHash &hs, StringHash &hs1) {
for (int len = 1; len <= m; len++) {
int i = 0, j = i + len;
if (!(j + len <= m && j <= m)) {
continue;
}
if (hs.get(i, j) == hs.get(j, j + len) &&
hs.get(j + len, m) == hs1.get(0, m - j - len)) {
return 1;
}
int i0 = m - len, j0 = m;
if (j <= i0 && hs.get(i, j) == hs.get(i0, j0) &&
hs.get(j, i0) == hs1.get(m - i0, m - j)) {
return 1;
}
}
return 0;
};
if (work(hs, hs1) || work(hs1, hs)) {
cout << "Yes\n";
return;
}
cout << "No\n";
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
init(5E5);
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}
F
二维前缀和,朴素解法 ,用双指针可以优化为 ,这里用的是枚举矩形宽,二分矩形长,复杂度 。
C++ Code
#include "bits/stdc++.h"
using namespace std;
using i64 = long long;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m, k;
cin >> n >> m >> k;
vector<vector<int>> a(n + 1, vector<int>(m + 1));
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
char ch;
cin >> ch;
if (ch == '.') {
a[i][j] = 1;
}
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
a[i][j] += a[i - 1][j] + a[i][j - 1] - a[i - 1][j - 1];
}
}
auto get = [&](int x1, int y1, int x2, int y2) {
return a[x2][y2] + a[x1][y1] - a[x2][y1] - a[x1][y2];
};
int ans = 1E9;
for (int i = 0; i < n; i++) {
for (int j = 0; j <= m; j++) {
for (int W = 0; i + W <= n; W++) {
int l = 0, r = m - j;
auto check = [&](int H) {
return get(i, j, i + W, j + H) >= k;
};
int H = -1;
while (l <= r) {
int mid = (l + r) >> 1;
if (check(mid)) {
r = mid - 1;
H = mid;
} else {
l = mid + 1;
}
}
if (H != -1) {
ans = min(ans, W * H);
}
}
}
}
if (ans == 1E9) {
cout << "No Solution\n";
} else {
cout << ans << '\n';
}
return 0;
}
G
最大生成树。
C++ Code
#include "bits/stdc++.h"
using namespace std;
using i64 = long long;
struct UnionFind {
int n;
vector<int> f;
UnionFind(const int &n) : n(n), f(n) {
iota(f.begin(), f.end(), 0);
}
int get(int x) {
return x == f[x] ? x : f[x] = get(f[x]);
}
bool unite(int x, int y) {
int gx = get(x), gy = get(y);
if (gx != gy) {
f[gx] = gy;
return 1;
}
return 0;
}
};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m;
cin >> n >> m;
UnionFind f(n);
i64 ans = 0;
vector<array<int, 3>> g;
for (int i = 0; i < m; i++) {
int u, v, w;
cin >> u >> v >> w;
u--;
v--;
g.push_back({w, u, v});
ans += w;
}
sort(g.begin(), g.end(), greater());
for (int i = 0; i < m; i++) {
if (f.unite(g[i][1], g[i][2])) {
ans -= g[i][0];
}
}
cout << ans << '\n';
return 0;
}
I
一直对折,对折到差不多了就再随便折一次。
C++ Code
#include "bits/stdc++.h"
using namespace std;
using i64 = long long;
void solve() {
int w, h, x, y;
cin >> w >> h >> x >> y;
auto work = [&](int now, int aim) {
if (now < aim) {
return (int) 1E9;
}
if (now == aim) {
return 0;
}
int cnt = 0;
int tmp = now;
while ((tmp + 1) / 2 > aim) {
cnt++;
tmp = (tmp + 1) / 2;
}
return cnt + 1;
};
int ans = min(work(w, x) + work(h, y), work(w, y) + work(h, x));
if (ans >= 1E9) {
cout << -1 << '\n';
return;
}
cout << ans << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}
J
令 ,则
C++ Code
#include "bits/stdc++.h"
using namespace std;
using i64 = long long;
void solve() {
int x, y;
cin >> x >> y;
if (x > y) {
cout << x + y << '\n';
return;
}
cout << y - (y % x) / 2 << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}
L
签到。