NOTE
A - Chompers
关键词:签到
Code
// Problem: AT ABC458 A// Contest: AtCoder - AtCoder Beginner Contest 458// URL: https://atcoder.jp/contests/abc458/tasks/abc458_a// Time: 2026-05-16 20:00:05#include <bits/stdc++.h>using namespace std;
// clang-format off#define endl '\n'#define all(x) (x).begin(), (x).end()#define fastio() ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);// clang-format on
using ll = long long;using ull = unsigned long long;using pii = pair<int, int>;using pdd = pair<double, double>;using pll = pair<long long, long long>;using i128 = __int128;
const int dx[] = {-1, 0, 1, 0, -1, 1, 1, -1};const int dy[] = {0, 1, 0, -1, 1, 1, -1, -1};const int inf = 0x3f3f3f3f;const int N = 0;
void solve(){ string s; int n;
cin >> s >> n;
for (int i = n; i < s.size() - n; i++) cout << s[i];}
int main(){ fastio();
int T = 1; // cin >> T;
while (T--) solve();
return 0;}B - Count Adjacent Cells
关键词:分类讨论
思路
考虑讨论三种情况。当 和 都为 时,答案是 ,当二者中有一个为 时,边界是单联通的,其余所有元素都是双联通。对于剩下的情况,四个角落是双联通,四条外侧边的中间部分是三联通,内部都是四联通。
Code
// Problem: AT ABC458 B// Contest: AtCoder - AtCoder Beginner Contest 458// URL: https://atcoder.jp/contests/abc458/tasks/abc458_b// Time: 2026-05-16 20:00:06#include <bits/stdc++.h>using namespace std;
// clang-format off#define endl '\n'#define all(x) (x).begin(), (x).end()#define fastio() ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);// clang-format on
using ll = long long;using ull = unsigned long long;using pii = pair<int, int>;using pdd = pair<double, double>;using pll = pair<long long, long long>;using i128 = __int128;
const int dx[] = {-1, 0, 1, 0, -1, 1, 1, -1};const int dy[] = {0, 1, 0, -1, 1, 1, -1, -1};const int inf = 0x3f3f3f3f;const int N = 0;
int n, m;
bool check(int x, int y){ if (x == 1 && y == 1) return true; if (x == 1 && y == m) return true; if (x == n && y == 1) return true; if (x == n && y == m) return true;
return false;}
void solve(){ cin >> n >> m;
if (n == 1 && m == 1) { cout << 0 << endl; return; }
for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { if (n == 1 || m == 1) { if (check(i, j)) cout << 1 << " "; else cout << 2 << " "; continue; }
if (check(i, j)) { cout << 2 << " "; continue; } if (i == 1 || i == n || j == m || j == 1) { cout << 3 << " "; continue; } cout << 4 << " "; } cout << endl; }}
int main(){ fastio();
int T = 1; // cin >> T;
while (T--) solve();
return 0;}C - C Stands for Center
关键词:推公式
思路
对于每个 ,由于要求子区间长度为奇数,所以我们考虑以 为中心向两侧扩展。容易知道,扩展的最远长度取决于它两侧元素数量的最小值,即 min(i, n - 1 - i)(下标从 开始)。
注意还要加 ,也就是不往外扩展的情况。此时子数组为 。
Code
// Problem: AT ABC458 C// Contest: AtCoder - AtCoder Beginner Contest 458// URL: https://atcoder.jp/contests/abc458/tasks/abc458_c// Time: 2026-05-16 20:00:07
#include <bits/stdc++.h>using namespace std;
// clang-format off#define endl '\n'#define all(x) (x).begin(), (x).end()#define fastio() ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);// clang-format on
using ll = long long;using ull = unsigned long long;using pii = pair<int, int>;using pdd = pair<double, double>;using pll = pair<long long, long long>;using i128 = __int128;
const int dx[] = {-1, 0, 1, 0, -1, 1, 1, -1};const int dy[] = {0, 1, 0, -1, 1, 1, -1, -1};const int inf = 0x3f3f3f3f;const int N = 0;
void solve(){ string s; cin >> s;
ll n = s.size(); vector<ll> pos;
ll res = 0; for (ll i = 0; i < s.size(); i++) { if (s[i] == 'C') { ll tmp = min(i, n - 1 - i); res += tmp + 1; } }
cout << res << endl;}
int main(){ fastio();
int T = 1; // cin >> T;
while (T--) solve();
return 0;}D - Chalkboard Median
关键词:STL
思路
一开始交了一发 ,考虑的是把所有数加入进一个 Multiset 里,并每次计算出中间位置的迭代器,但迭代器移动函数 advance() 和 distance() 函数都是 的,会超时。
我们考虑优化策略。注意到每次增加两个数,我们可以通过检验两个数和现有中间的数的大小关系。
假如现在集合里只有一个元素 ,如果新加入两个比 小的数,显然迭代器应该往左移动一个位置。同理,如果新加入两个比 大(或者等于 )的数,迭代器应该往右移动一个位置。如果一大一小,迭代器保持不动即可。
NOTE在 C++ 的
std::multiset中,如果插入一个和已有元素相等的数,默认会把它插入到相同元素的最右侧。也就是说,如果
p == *it,它会被放到it的右边,不会影响it左侧的计数。
Code
// Problem: AT ABC458 D// Contest: AtCoder - AtCoder Beginner Contest 458// URL: https://atcoder.jp/contests/abc458/tasks/abc458_d// Time: 2026-05-16 20:00:08#include <bits/stdc++.h>using namespace std;
// clang-format off#define endl '\n'#define all(x) (x).begin(), (x).end()#define fastio() ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);// clang-format on
using ll = long long;using ull = unsigned long long;using pii = pair<int, int>;using pdd = pair<double, double>;using pll = pair<long long, long long>;using i128 = __int128;
const int dx[] = {-1, 0, 1, 0, -1, 1, 1, -1};const int dy[] = {0, 1, 0, -1, 1, 1, -1, -1};const int inf = 0x3f3f3f3f;const int N = 0;
void solve(){ int x, q; cin >> x >> q;
multiset<int> s; s.insert(x);
auto it = s.begin();
while (q--) { int p, y; cin >> p >> y;
s.insert(p); s.insert(y);
int cnt = 0; if (p < *it) cnt++; if (y < *it) cnt++;
if (cnt == 2) --it; else if (cnt == 0) ++it;
cout << *it << endl; }}
int main(){ fastio();
int T = 1; // cin >> T;
while (T--) solve();
return 0;}E - Count 123
关键词:组合数学
思路
注意到 是万能数字,我们考虑先排出一个只有 和 的序列,在这个序列中 和 允许相邻,但每一次相邻都必须在中间放入至少一个 。
假设我们排出的 1、3 序列中,恰好有 个交界处(比如 1 1 3 1 中,1到3有 1 个,3到1有 1 个,共 2 个交界)。为了修复这 个非法交界,我们必须强制消耗 个 2垫在中间。原本有 个 2,强制消耗了 个,还剩 个 2。
现在 1 和 3 的总数是 个,它们之间以及最左最右,一共提供了 个空位。
把剩下的 个相同的 2,放入这 个允许为空的槽位里,方案数为:
下面我们考虑如何计算交界的数量。也就是有多少种排法,能让 1 和 3 产生恰好 个交界?
我们设 为一个基础块数,分奇偶讨论:
-
当 (奇数个交界):
序列一定是
1...3或3...1这样交替。这意味着1有 个段,3也有 个段。将 分成 段方案数是 ,将 分成 段是 。
两种开头方式,总排法为:
-
当 (偶数个交界):
序列一定是
1...1或3...3这样交替。-
如果是
1...1:1有 个段,3有 个段。排法为 。 -
如果是
3...3:1有 个段,3有 个段。排法为 。总排法就是这两者相加。
-
我们只需要枚举 ,算出对应的 ,把排法数 剩下的随便放 2 的方案数累加起来即可。
Code
// Problem: AT ABC458 E// Contest: AtCoder - AtCoder Beginner Contest 458// URL: https://atcoder.jp/contests/abc458/tasks/abc458_e// Time: 2026-05-16 20:00:09#include <bits/stdc++.h>using namespace std;
// clang-format off#define endl '\n'#define all(x) (x).begin(), (x).end()#define fastio() ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);// clang-format on
using ll = long long;using ull = unsigned long long;using pii = pair<int, int>;using pdd = pair<double, double>;using pll = pair<long long, long long>;using i128 = __int128;
const int dx[] = {-1, 0, 1, 0, -1, 1, 1, -1};const int dy[] = {0, 1, 0, -1, 1, 1, -1, -1};const int inf = 0x3f3f3f3f;const int N = 3e6 + 5;
using u32 = uint32_t;using u64 = uint64_t;
template<class T>constexpr T power(T a, u64 b, T res = 1){ for (; b != 0; b /= 2, a *= a) { if (b & 1) res *= a; } return res;}
template<class U, U P>struct ModIntBase{public: U x; constexpr ModIntBase() : x(0) { }
constexpr ModIntBase(long long x_) { long long v = x_ % (long long) P; if (v < 0) v += (long long) P; x = (U) v; }
constexpr static U mod() { return P; } constexpr U val() const { return x; }
constexpr ModIntBase operator-() const { return ModIntBase(x == 0 ? 0 : P - x); }
constexpr ModIntBase inv() const { return power(*this, P - 2); }
constexpr ModIntBase &operator*=(const ModIntBase &rhs) & { x = (u64) x * rhs.x % P; return *this; } constexpr ModIntBase &operator+=(const ModIntBase &rhs) & { x += rhs.x; if (x >= P) x -= P; return *this; } constexpr ModIntBase &operator-=(const ModIntBase &rhs) & { if (x < rhs.x) x += P; x -= rhs.x; return *this; } constexpr ModIntBase &operator/=(const ModIntBase &rhs) & { return *this *= rhs.inv(); }
constexpr ModIntBase &operator++() & { x++; if (x == P) x = 0; return *this; } constexpr ModIntBase &operator--() & { if (x == 0) x = P; x--; return *this; }
constexpr ModIntBase operator++(int) { ModIntBase res = *this; ++(*this); return res; } constexpr ModIntBase operator--(int) { ModIntBase res = *this; --(*this); return res; }
friend constexpr ModIntBase operator*(ModIntBase lhs, const ModIntBase &rhs) { return lhs *= rhs; } friend constexpr ModIntBase operator+(ModIntBase lhs, const ModIntBase &rhs) { return lhs += rhs; } friend constexpr ModIntBase operator-(ModIntBase lhs, const ModIntBase &rhs) { return lhs -= rhs; } friend constexpr ModIntBase operator/(ModIntBase lhs, const ModIntBase &rhs) { return lhs /= rhs; }
friend istream &operator>>(istream &is, ModIntBase &a) { long long v; is >> v; a = ModIntBase(v); return is; } friend ostream &operator<<(ostream &os, const ModIntBase &a) { return os << a.val(); } friend bool operator==(const ModIntBase &lhs, const ModIntBase &rhs) { return lhs.val() == rhs.val(); }
friend bool operator!=(const ModIntBase &lhs, const ModIntBase &rhs) { return lhs.val() != rhs.val(); }};
constexpr u32 MOD = 998244353;using Z = ModIntBase<u32, MOD>;
struct Comb{ int n; vector<Z> _fac; vector<Z> _invfac; vector<Z> _inv;
Comb() : n(1), _fac(2), _invfac(2), _inv(2) { _fac[0] = _fac[1] = 1; _invfac[0] = _invfac[1] = 1; _inv[1] = 1; }
Comb(int n) : Comb() { init(n); }
void init(int m) { if (m <= n) return;
int old = n;
_fac.resize(m + 1); _invfac.resize(m + 1); _inv.resize(m + 1);
for (int i = old + 1; i <= m; i++) { _fac[i] = _fac[i - 1] * i; }
_invfac[m] = _fac[m].inv();
for (int i = m; i > old; i--) { _invfac[i - 1] = _invfac[i] * i; _inv[i] = _invfac[i] * _fac[i - 1]; }
n = m; }
Z fac(int m) { if (m > n) init(2 * m); return _fac[m]; }
Z invfac(int m) { if (m > n) init(2 * m); return _invfac[m]; }
Z inv(int m) { if (m > n) init(2 * m); return _inv[m]; }
Z binom(int n, int m) { if (m < 0 || m > n) return 0; return fac(n) * invfac(m) * invfac(n - m); }
Z perm(int n, int m) { if (m < 0 || m > n) return 0; return fac(n) * invfac(n - m); }} comb;
void solve(){ int x1, x2, x3; cin >> x1 >> x2 >> x3;
comb.init(x1 + x2 + x3 + 5);
if (x1 == 0) { cout << comb.binom(x2 + x3, x3) << endl; return; } if (x3 == 0) { cout << comb.binom(x1 + x2, x1) << endl; return; }
Z res = 0; int lim = min(x1, x2 + 1);
for (int k = 1; k <= lim; k++) { Z a = comb.binom(x2 + 1, k); Z b = comb.binom(x1 - 1, k - 1); Z c = comb.binom(x2 + x3 - k, x3);
res += a * b * c; }
cout << res << endl;}
int main(){ fastio();
int T = 1; // cin >> T;
while (T--) solve();
return 0;}