777 字
2 分钟
Atcoder_Beginner_Contest_471(A~E题)
2026-08-16
浏览量 18 · 访客 5

壁纸链接
题目链接:https://atcoder.jp/contests/abc471/tasks

A - Nine or Nein#

分别计算A+BA+BABA-BA×BA\times BA÷BA\div B,判断其中是否至少有一个结果等于99。由于BB为正整数,不需要处理除数为00的情况。满足任意一个条件就输出NineNine,否则输出NeinNein

void solve(){
int a, b;
cin >> a >> b;
if(a + b == 9 || a - b == 9 || a * b == 9 || a * 1.0 / b == 9)
cout << "Nine" << endl;
else cout << "Nein" << endl;
}

B - Survey Tabulation#

题目不区分大小写,所以需要先把每个字符串转换成统一形式,再进行频次统计。代码将所有小写字母映射为对应的大写字母,从而使仅大小写不同的字符串得到相同的键。
使用mapmap记录规范化后每个字符串出现的次数,并在插入时同步维护最大频次ansans。设所有字符串的总长度为LL,时间复杂度为O(LlogN)O(LlogN)

void solve(){
int n; cin >> n;
int ans = 0;
map<string, int> mp;
for(int i = 1; i <= n;i++){
string s;
cin >> s;
for(auto& it : s){
if(it - 'a' >= 0){
it = char('A' + it -'a');
}
}
mp[s]++;
ans = max(mp[s], ans);
}
cout << ans << endl;
}

C - Cookies and Greedy Takahashi#

将所有负坐标从大到小排序,所有正坐标从小到大排序。这样在任意时刻,负半轴上尚未访问且最靠近当前位置的候选点一定是neg[i]neg[i],正半轴上的对应候选点一定是pos[j]pos[j],其他未访问点都位于这两个边界点的外侧,不可能更近。
因此每一步只需要比较当前坐标xxneg[i]neg[i]pos[j]pos[j]的距离。若一侧已经取完,就选择另一侧;否则选择距离更小的一侧。两者距离相等时,负坐标更小,按照题目的次级规则应优先选择负侧,所以代码在xneg[i]pos[j]xx-neg[i]\leq pos[j]-x时移动到neg[i]neg[i]
每个坐标只会被访问一次,排序后的双指针模拟为O(N)O(N),加上排序后总时间复杂度为O(NlogN)O(NlogN),空间复杂度为O(N)O(N)

void solve(){
int n; cin >> n;
vector<ll> neg(n), pos(n);
for(int i = 1; i <= n;i++){
int x; cin >> x;
if(x < 0) neg.push_back(x);
else pos.push_back(x);
}
sort(neg.begin(), neg.end(), greater<ll>());
sort(pos.begin(), pos.end());
ll ans = 0, x = 0;
int i = 0, j = 0;
int neg_ptr = (int)neg.size(), pos_ptr = (int)pos.size();
while(i < neg_ptr || j < pos_ptr){
if(j == pos_ptr || (i < neg_ptr && x - neg[i] <= pos[j] - x)){
ans += x - neg[i];
x = neg[i];
i++;
}
else{
ans += pos[j] - x;
x = pos[j];
j++;
}
}
cout << ans << endl;
}

D - Chargers#

对于在时刻t0t_0插入、初始电量为ww的电池,它达到满电的时刻为 key=t0+(Vw)key=t_0+(V-w)。 在后续时刻tt,其电量可以写成min(V,tkey+V)\min(V,t-key+V)。对于固定的查询时刻tt,这个值关于keykey单调不增,因此keykey越小,当前电量越大。问题就转化为动态维护所有电池的keykey,每次取出最小值。
代码使用multisetmultiset保存keykey。插入操作加入t+(Vw)t+(V-w);取出操作删除集合中的最小元素,并用min(V,tkey+V)\min(V,t-key+V)还原当前电量。如果集合为空则输出1-1。每次操作的时间复杂度为O(logQ)O(logQ),总时间复杂度为O(QlogQ)O(QlogQ),空间复杂度为O(Q)O(Q)

void solve(){
int Q; ll V;
cin >> Q >> V;
multiset<ll> st;
while(Q--){
int op; cin >> op;
if(op == 1){
int t; ll w;
cin >> t >> w;
st.insert(t + (V - w));
}
else{
int t; cin >> t;
if(st.empty()) cout << -1 << '\n';
else{
ll val = *st.begin();
st.erase(st.begin());
ll cur = t - val + V;
if(cur > V) cur = V;
cout << cur << '\n';
}
}
}
}

E - Sum of Square of Sum#

对于一个选出的大小为KK的下标集合SS,将平方展开可得 (iSAi)2=iSAi2+2i<j, i,jSAiAj(\sum_{i\in S}A_i)^2=\sum_{i\in S}A_i^2+2\sum_{i<j,\ i,j\in S}A_iA_j
固定一个下标ii,包含它的大小为KK的集合共有(N1K1)\binom{N-1}{K-1}个,所以所有单项平方的总贡献为 (N1K1)iAi2\binom{N-1}{K-1}\sum_i A_i^2
固定一对不同下标i,ji,j,同时包含它们的集合共有(N2K2)\binom{N-2}{K-2}个。又因为 (iAi)2iAi2=2i<jAiAj(\sum_i A_i)^2-\sum_i A_i^2=2\sum_{i<j}A_iA_j, 所以所有交叉项的总贡献为 (N2K2)((iAi)2iAi2)\binom{N-2}{K-2}\left((\sum_i A_i)^2-\sum_i A_i^2\right)
我们只需要预处理阶乘和逆阶乘来计算两个组合数,再将两部分贡献相加。预处理与求和的时间复杂度为O(N+logMOD)O(N+logMOD),空间复杂度为O(N)O(N)

void solve(){
ll n, k;
cin >> n >> k;
ll s1 = 0, s2 = 0;
vector<ll> A(n);
for(ll i = 0; i < n;i++){
cin >> A[i];
A[i] %= mod;
s1 = (s1 + A[i]) % mod;
s2 = (s2 + A[i] * A[i]) % mod;
}
vector<ll> fact(n + 1), inv_fact(n + 1);
fact[0] = 1;
for(ll i = 1; i <= n;i++){
fact[i] = fact[i - 1] * i % mod;
}
inv_fact[n] = fast_pow(fact[n], mod - 2, mod);
for(ll i = n; i >= 1; i--){
inv_fact[i - 1] = inv_fact[i] * i % mod;
}
ll c1 = C(n - 1, k - 1, fact, inv_fact);
ll c2 = C(n - 2, k - 2, fact, inv_fact);
ll cross = (s1 * s1 % mod - s2 + mod) % mod;
ll ans = (c1 * s2 % mod + c2 * cross % mod) % mod;
cout << ans << endl;
}

模板:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
#define mod 998244353
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
ll fast_pow(ll a, ll b, ll MOD){
ll ans = 1;
while(b){
if(b & 1) ans = (ans * a) % MOD;
b >>= 1;
a = (a * a) % MOD;
}
return ans;
}
vector<ll> get_inverse(ll n, ll MOD){
vector<ll> inverse(n + 1, 0);
inverse[1] = 1;
for(int i = 2; i <= n;i++){
inverse[i] = MOD - (MOD / i) * inverse[MOD % i] % MOD;
}
return inverse;
}
void solve(){
}
int main(){
ios::sync_with_stdio(false),
cin.tie(nullptr), cout.tie(nullptr);
int _ = 1;
//cin >> _;
while(_--){
solve();
}
return 0;
}
分享

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

Atcoder_Beginner_Contest_471(A~E题)
https://mkrari.cn/posts/abc_471/
作者
Mkrari
发布于
2026-08-16
许可协议
CC BY-NC-SA 4.0