题目链接:https://atcoder.jp/contests/abc459/tasks
A - Hell, World!
不输出第位字符即可。
#include <bits/stdc++.h>
using namespace std;using ll = long long;#define endl '\n'#define mod 998244353typedef 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 998244353typedef 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
这题不能直接模拟,我们需要一步一步对遍历的步骤进行优化。
这里我们开个数组表示个格子。然后看到操作是输出至少有多少个格子有对应数量的积木,那我们就再开一个数组记录满足对应至少满足这么多积木数量的格子的数量,然后在每次进行操作时对对应的(积木数量)加。(这样的数组里面存的是达到过这个积木数量的格子数量,也就是大于等于这个积木数量的格子数量,满足题目的”至少”的要求)而对于操作提到的所有格子都有的数量就会拿走,我们肯定不能遍历去减。这里的方法是用记录下对应的积木数量(也就是所有格子都有的积木数量),然后在操作查询时输出(也就是减去之后操作查询时需要满足的积木数量)即可。
这里的会超过,我们要把数组开大一点。或者加个条件判断就输出。
#include <bits/stdc++.h>
using namespace std;using ll = long long;#define endl '\n'#define mod 998244353typedef 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
我们先记录字符串中每个字符出现的频率。然后我们可以发现,我们将出现频率最大的字符(它的出现次数我记为)与其他字符通过间隔构造,使得构造的字符串能满足题目条件的一个关键条件是: - (其他字符出现的总次数) > 。所以只要满足这个条件我们就,否则就。如果我们就通过构造输出其中满足条件的一个字符串。我这里的构造是每次都找到非末尾元素的出现次数最多的字符拼接到末尾,然后输出。
#include <bits/stdc++.h>
using namespace std;using ll = long long;#define endl '\n'#define mod 998244353typedef 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
这题没有想象中那么难,思路比较清晰。
我们的思路是从叶子节点不断向父节点遍历。我们可以这样思考,如果先让较小的松鼠在父节点取了一部分糖果,它取的糖果就可能是子树的任何部分,那我们在计算该父节点的子树取的糖果就会非常混乱。反之,如果我们先让对应的叶子节点的松鼠在叶子节点取,然后如果有取剩的就传递给父节点,这样倒序遍历的话,我们就可以保证每次父节点的子树都是被取过的。而对于每一个子树部分,松鼠可以随意取子树任何分支的糖果,这里其实就是一个组合数的问题,对于每一个松鼠取法就是种。(是对应的松鼠需要的糖果数量,是当前整个子树中可供取的糖果数量)我们从叶子节点不断向上遍历,并在每一次节点计算该子树所有组合的总数然后加入最终就可以得到结果。
这里每次计算组合数时的除法取模运算要注意需要通过提前预处理逆元来快速进行模运算除法。
#include <bits/stdc++.h>
using namespace std;using ll = long long;#define endl '\n'#define mod 998244353typedef 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;}