Codeforces Round 925 (Div. 3) A-F 训练记录
链接:https://codeforces.com/contest/1931
难度自评:A < B = C < E < F < D < G(??
算是很简单的一场 div3。
A. Recovering a Small String
优先放第三个,放满了再放第二个,最后是第一个。
需要注意的是,仨位置都至少有一个。
#include <iostream>
using namespace std;
void solve(){
int n; cin >> n;
int a = 1, b = 1, c = 1; n -= 3;
while(n--){
if(c < 26) c++;
else if(b < 26) b++;
else a++;
}
cout << (char)('a' + a - 1) << (char)('a' + b - 1) << (char)('a' + c - 1) << '\n';
}
int main(){
int _; cin >> _; while(_--) solve();
return 0;
}
B. Make Equal
如果最后能全都相等,显然每一个都取到了平均值。
所以我们先算一下 avg
,再根据每个 a[i]
多退少补即可。
如果中间不够了就直接输出 NO
。
#include <iostream>
#include <vector>
#define int long long
using namespace std;
bool solve(){
int n; cin >> n;
vector <int> a(n+1);
int sum = 0;
for(int i = 1; i <= n; i++){
cin >> a[i];
sum += a[i];
}
if(sum % n) return false;
sum /= n; int t = 0;
for(int i = 1; i <= n; i++){
if(a[i] > sum) t += a[i] - sum;
else if(a[i] + t < sum) return false;
else{
t -= sum - a[i];
}
}
return true;
}
signed main(){
int _; cin >> _; while(_--) cout << (solve() ? "YES" : "NO") << '\n';
return 0;
}
C. Make Equal Again
显然,找两边最长连续相同段即可,如果相同可以都算上,不同的话算大的一边。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
void solve(){
int n; cin >> n;
vector <int> a(n+1);
for(int i = 1; i <= n; i++) cin >> a[i];
int l = 2, r = n-1;
while(a[l] == a[l-1]) l++;
while(a[r] == a[r+1]) r--;
r = n - r; l--;
if(a[1] != a[n])
cout << n - max(l, r) << endl;
else
cout << max(0, n - l - r) << endl;
}
int main(){
int _; cin >> _; while(_--) solve();
return 0;
}
D. Divisible Pairs
这是一个不太好的写法,其实开一个 map <pii, int>
就够同时处理
x
x
x 和
y
y
y 了。
由题:
- ( a i + a j ) m o d x = 0 (a_i + a_j) \mod x = 0 (ai+aj)modx=0
- ( a i − a j ) m o d y = 0 (a_i - a_j) \mod y = 0 (ai−aj)mody=0
可以转化为:
- a i m o d x = x − a j m o d x a_i \mod x = x - a_j \mod x aimodx=x−ajmodx
- a i m o d y = a j m o d y a_i \mod y = a_j \mod y aimody=ajmody
#include <iostream>
#include <vector>
#include <map>
#define int long long
using namespace std;
void solve(){
int n, x, y; cin >> n >> x >> y;;
vector <int> a(n+1);
map <int, int> mpx; map <int, vector <int> > mpy;
for(int i = 1; i <= n; i++) cin >> a[i];
for(int i = 1; i <= n; i++) mpy[a[i] % y].emplace_back(a[i]);
int ans = 0;
for(auto [_, v] : mpy){
mpx.clear();
for(auto i : v){
ans += mpx[(x - i % x) % x];
mpx[i % x]++;
}
}
cout << ans << '\n';
}
signed main(){
ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
int _; cin >> _; while(_--) solve();
return 0;
}
E. Anna and the Valentine’s Day Gift
由于最后答案是判断 x x x 和 1 0 m 10^m 10m 的大小关系,所以答案取决于长度而非大小。
只考虑长度,容易发现:
- A n n a \mathcal{Anna} Anna 一次翻转,可以把末尾的 0 0 0 全都去掉,对答案的贡献取决于末尾 0 0 0 的长度。
- S a s h a \mathcal{Sasha} Sasha 一次合并,并不影响其长度之和,但会把 xxx00 合并到 xxxxx 前面变成 xxx00xxxxx,这样 A n n a \mathcal{Anna} Anna 就没办法去掉这个 0 0 0。
所以,我们只需要按末尾 0 0 0 的个数从大到小排序,将 A n n a \mathcal{Anna} Anna 能去掉的 0 0 0 去掉,剩下的数字个数即为答案。
#include <iostream>
#include <vector>
#include <algorithm>
#include <deque>
#include <string>
#define int long long
using namespace std;
struct item{
string s;
int z;
};
void solve(){
int n, m; cin >> n >> m;
vector <item> a(n);
for(int i = 0; i < n; i++){
cin >> a[i].s;
int p = a[i].s.size() - 1;
while(a[i].s[p] == '0') p--;
a[i].z = a[i].s.size() - p - 1;
}
sort(a.begin(), a.end(), [](item x, item y){ return x.z > y.z; });
int cnt = 0, sum = 0;
for(int i = 0; i < n; i++){
sum += a[i].s.size();
if(!(i & 1)) cnt += a[i].z;
}
cout << (sum - cnt > m ? "Sasha" : "Anna") << '\n';
}
signed main(){
int _; cin >> _; while(_--) solve();
return 0;
}
F. Chat Screenshots
由于每次只是把截图的人拉到了首位,所以 [ 2 , n ] [2, n] [2,n] 区间内是按照原先顺序的。
容易想到拓扑排序的做法,我们只需要对 [ 2 , n ] [2, n] [2,n] 区间内相邻的数建边,再跑拓扑排序判环即可。
另外,由于题目中提到 n ⋅ k ≤ 2 × 1 0 5 n \cdot k \le 2 \times 10^5 n⋅k≤2×105,所以建图的复杂度是正确的。
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
bool solve(){
int n, k; cin >> n >> k;
vector <int> inc(n+1);
vector < vector <int> > e(n+1);
for(int i = 1; i <= k; i++){
vector <int> inp(n);
for(auto &x : inp) cin >> x;
for(int j = 1; j < n - 1; j++){
e[inp[j]].emplace_back(inp[j+1]);
inc[inp[j+1]]++;
}
}
queue <int> q; int cnt = 0;
for(int i = 1; i <= n; i++){
if(!inc[i]){
q.emplace(i);
}
}
while(!q.empty()){
int u = q.front(); q.pop();
cnt++;
for(auto v : e[u]){
if(--inc[v] == 0){
q.emplace(v);
}
}
}
return cnt == n;
}
int main(){
int _; cin >> _; while(_--) cout << (solve() ? "YES" : "NO") << '\n';
return 0;
}