911 字
2 分钟
Atcoder_Beginner_Contest_459(A~E题)
2026-05-25
统计加载中...

题目链接:https://atcoder.jp/contests/abc459/tasks

A - Hell, World!#

不输出第XX位字符即可。

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define endl '\n'
#define mod 998244353
typedef pair<ll, ll> pll;
void solved() {
int x;
cin >> x;
string s = "HelloWorld";
for(int i = 0; i < (int)s.size(); i++){
if(i != x - 1){
cout << s[i];
}
}
}
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int _ = 1;
while(_--){
solved();
}
return 0;
}

B - 459#

直接循环判断然后拼接对应的数字即可。

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define endl '\n'
#define mod 998244353
typedef pair<ll, ll> pll;
void solved() {
int n;
cin >> n;
vector<string> s(n);
for(auto& it : s){
cin >> it;
}
string t = "";
for(auto it : s){
if(it[0] == 'a' || it[0] == 'b' || it[0] == 'c'){
t += "2";
}
if(it[0] == 'd' || it[0] == 'e' || it[0] == 'f'){
t += "3";
}
if(it[0] == 'g' || it[0] == 'h' || it[0] == 'i'){
t += "4";
}
if(it[0] == 'j' || it[0] == 'k' || it[0] == 'l'){
t += "5";
}
if(it[0] == 'm' || it[0] == 'n' || it[0] == 'o'){
t += "6";
}
if(it[0] == 'p' || it[0] == 'q' || it[0] == 'r' || it[0] == 's'){
t += "7";
}
if(it[0] == 't' || it[0] == 'u' || it[0] == 'v'){
t += "8";
}
if(it[0] == 'w' || it[0] == 'x' || it[0] == 'y' || it[0] == 'z'){
t += "9";
}
}
cout << t << endl;
}
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int _ = 1;
while(_--){
solved();
}
return 0;
}

C - Drop Blocks#

这题不能直接模拟,我们需要一步一步对遍历的步骤进行优化。
这里我们开个数组aa表示nn个格子。然后看到操作22是输出至少有多少个格子有对应数量的积木,那我们就再开一个数组b[y]b[y]记录满足对应至少满足这么多积木数量yy的格子的数量,然后在每次进行11操作时对对应的a[y]a[y](积木数量)加11。(这样的bb数组里面存的是达到过这个积木数量的格子数量,也就是大于等于这个积木数量的格子数量,满足题目的”至少”的要求)而对于操作11提到的所有格子都有的数量就会拿走,我们肯定不能遍历去减。这里的方法是用mimi记录下b[y]=nb[y] = n对应的积木数量yy(也就是所有格子都有的积木数量yy),然后在22操作查询时输出b[y+mi]b[y + mi](也就是减去yy之后22操作查询时需要满足的积木数量y+miy + mi)即可。
tipstips:这里的y+miy + mi会超过3×1053 \times 10^5,我们要把数组开大一点。或者加个条件判断y+mi>qy + mi > q就输出00

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define endl '\n'
#define mod 998244353
typedef pair<ll, ll> pll;
int a[500010];
int b[500010];
int mi = 0;
void solved() {
int n, q;
cin >> n >> q;
while(q--){
int x, y;
cin >> x >> y;
if(x == 1){
a[y]++; b[a[y]]++;
if(b[a[y]] == n) mi = a[y];
}
else{
cout << b[y + mi] << endl;
}
}
}
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int _ = 1;
while(_--){
solved();
}
return 0;
}

D - Adjacent Distinct String#

我们先记录字符串中每个字符出现的频率。然后我们可以发现,我们将出现频率最大的字符(它的出现次数我记为mama)与其他字符通过间隔构造,使得构造的字符串能满足题目条件的一个关键条件是:mama - otherother(其他字符出现的总次数) > 11。所以只要满足这个条件我们就yesyes,否则就nono。如果yesyes我们就通过构造输出其中满足条件的一个字符串。我这里的构造是每次都找到非末尾元素的出现次数最多的字符拼接到tt末尾,然后输出tt

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define endl '\n'
#define mod 998244353
typedef pair<ll, ll> pll;
map<char, int> mp;
void solved() {
int t;
cin >> t;
while(t--){
mp.clear();
int ma = 0;
string s; cin >> s;
for(auto it : s) mp[it]++;
for(auto it : mp){
if(it.second > ma) ma = it.second;
}
int other = (int)s.size() - ma;
if(ma - other > 1) cout << "No" << endl;
else{
cout << "Yes" << endl;
string t = "";
int cnt = (int)s.size();
while(cnt--){
int max_ = 0; char c ='0';
for(auto it : mp){
if(it.second > max_ &&(t.empty() || it.first != t.back())){
max_ = it.second;
c = it.first;
}
}
t += c; mp[c]--;
}
cout << t << endl;
}
}
}
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int _ = 1;
while(_--){
solved();
}
return 0;
}

E - Select from Subtrees#

这题没有想象中那么难,思路比较清晰。
我们的思路是从叶子节点不断向父节点遍历。我们可以这样思考,如果先让ii较小的松鼠在父节点取了一部分糖果,它取的糖果就可能是子树的任何部分,那我们在计算该父节点的子树取的糖果就会非常混乱。反之,如果我们先让对应的叶子节点的松鼠在叶子节点取,然后如果有取剩的就传递给父节点,这样倒序遍历的话,我们就可以保证每次父节点的子树都是被取过的。而对于每一个子树部分,松鼠可以随意取子树任何分支的糖果,这里其实就是一个组合数的问题,对于每一个松鼠取法就是Csumd[x]C_{sum}^{d[x]}种。(d[x]d[x]是对应的松鼠xx需要的糖果数量,sumsum是当前整个子树中可供取的糖果数量)我们从叶子节点不断向上遍历,并在每一次节点计算该子树所有组合的总数然后加入ansans最终就可以得到结果。
tipstips:这里每次计算组合数时的除法取模运算要注意需要通过提前预处理逆元来快速进行模运算除法。

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define endl '\n'
#define mod 998244353
typedef pair<ll, ll> pll;
int n;
ll a[200010];
ll d[200010];
ll ans = 1;
vector<vector<int>> child;
vector<ll> inv;
ll dfs(int x, vector<ll>& inv){
ll sum = a[x];
for (int v : child[x]){
sum += dfs(v, inv);
}
if(sum < d[x]) ans = 0;
else {
// 计算组合数C(d[k], sum)
for (int i = 0; i < d[x];i++){
ll num = (sum - i) % mod;
if (num < 0) num += mod;
ans = ans * num % mod;
ans = ans * inv[i + 1] % mod; //除法模运算:除以(i + 1)取模等价于乘逆元
}
}
return sum - d[x]; //将未使用的糖果传递给父节点
}
void solved() {
cin >> n;
child.resize(n + 1);
for(int i = 2; i <= n;i++){
int x;
cin >> x;
child[x].push_back(i);
}
int maxd = 0; //找出需要处理的最大逆元
for (int i = 1; i <= n;i++) cin >> a[i];
for (int i = 1; i <= n;i++){
cin >> d[i];
if(d[i] > maxd) maxd = d[i];
}
//线性预处理逆元,用于快速进行模除法
inv.resize(maxd + 2);
inv[1] = 1;
for (int i = 2; i <= maxd;i++){
inv[i] = mod - mod / i * inv[mod % i] % mod;
}
//从根节点开始
dfs(1, inv);
cout << ans % mod << endl;
}
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int _ = 1;
// cin >> _;
while(_--){
solved();
}
return 0;
}
分享

如果这篇文章对你有帮助,欢迎分享给更多人!

Atcoder_Beginner_Contest_459(A~E题)
https://mkrari.cn/posts/abc_459/
作者
Mkrari
发布于
2026-05-25
许可协议
CC BY-NC-SA 4.0