AtCoder Beginner Contest 350
补题链接 未补(F~G)
A - Past ABCs
题目描述
您将获得一个长度为 \(6\) 的字符串 \(S\) 。保证 \(S\) 的前三个字符是“ABC”,后三个字符是数字。
确定 \(S\) 是否为本次竞赛开始前在 AtCoder 上举行并结束的竞赛的缩写。
此处,字符串 \(T\) 是“本次比赛开始前在 AtCoder 上举行并结束的比赛的缩写”当且仅当它等于以下 \(348\) 字符串之一:
ABC001、ABC002、 \(\ldots\) 、ABC314、ABC315、ABC317、ABC318、 \(\ldots\) 、ABC348、ABC349。
请注意,不包括“ABC316”。
分析
已经保证了前三个字符的合法性,那么只需要判断后三个是否合法
又因为保证了后三个是数字,那么把后三个转换成\(int\)更容易判断合法性
代码
#include <bits/stdc++.h>
#define int long long
#define all(x) (x).begin(), (x).end()
#define len(x) (x).size()
#define endl '\n'
#define lowbit(x) ((x) & - (x))
//using namespace std;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
signed main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
//std::cout.precision(10);
std::string s;
std::cin >> s;
//substr(idx, len)从字符串下标为idx的位置开始,截取长度为len的字符串
//stoi(str)将字符串str转换成整数
int x = std::stoi(s.substr(3, 3));
if(x >= 1 && x <= 349 && x != 316)
std::cout << "Yes";
else
std::cout << "No";
return 0;
}
B - Dentist Aoki
题目描述
高桥有 \(N\) 颗牙齿,每个编号为 \(1, 2, \dots, N\) 的孔中都有一颗。
牙医青木将对这些牙齿和洞进行 \(Q\) 治疗。
在第 \(i\) 次处理中,孔 \(Ti\) 的处理如下:
- 如果孔 \(T i\) 中有齿,请将齿从孔 \(T i\) 中取出。
- 如果孔 \(T i\) 中没有齿(即孔是空的),则在孔 \(T i\) 中长出齿。
所有治疗完成后,高桥有多少颗牙齿?
分析
令\(0\)表示没牙齿,\(1\)表示有牙齿
对于每次操作当前位置的值为\(0\)就改为\(1\),当前位置的值为\(1\)就改为\(0\)
那么这个操作可以用异或(相同为0,不同为1)来实现,异或1
1 ^ 1 相同 ---> 0
0 ^ 1 不同 ---> 1
代码
#include <bits/stdc++.h>
#define int long long
#define all(x) (x).begin(), (x).end()
#define len(x) (x).size()
#define endl '\n'
#define lowbit(x) ((x) & - (x))
//using namespace std;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
signed main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
//std::cout.precision(10);
int n, q;
std::cin >> n >> q;
std::vector<int> f(n + 1, 1);//一开始每个孔都有牙齿
while(q--) {
int x;
std::cin >> x;
f[x] ^= 1;
}
int cnt = 0;
for(int i = 1; i <= n; i++) {
if(f[i])
cnt++;
}
std::cout << cnt;
return 0;
}
C - Sort
题目描述
您将获得 \((1,2,\ldots,N)\) 的排列 \(A=(A 1,\ldots,A N)\) 。
通过在 \(0\) 到 \(N-1\) 次(含)之间执行以下操作,将 \(A\) 转换为 \((1,2,\ldots,N)\) :
- 操作:选择任意一对整数 \((i,j)\) ,使得 \(1\leq i j \leq N\) 。交换 \(A\) 的第 \(i\) 个位置和第 \(j\) 个位置的元素。
可以证明,在给定的约束条件下,总是可以将 \(A\) 变换为 \((1,2,\ldots,N)\) 。
分析
给定\(1\)到\(n\)的排列\(A\),让我们通过一定操作使得\(Ai = i\)
因此我们的目标是通过交换位置这一手段将每个数放在合法位置上,我们只需要每次把位置不合法的数放在合法位置即可
证明最大为\(n-1\)次:
假设所有数都不在合法位置,我们可以通过\(n - 1\)次操作把前\(n - 1\)个数放在合法位置,那么第\(n\)个数自然而然在合法位置
代码
#include <bits/stdc++.h>
#define int long long
#define all(x) (x).begin(), (x).end()
#define len(x) (x).size()
#define endl '\n'
#define lowbit(x) ((x) & - (x))
//using namespace std;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
signed main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
//std::cout.precision(10);
std::map<int, int> find;
int n;
std::cin >> n;
std::vector<int> a(n + 1), have;
for(int i = 1; i <= n; i++) {
std::cin >> a[i];
if(a[i] != i) {
find[a[i]] = i;
//收集不合法的数
have.push_back(a[i]);
}
}
//从大到小排序
std::sort(all(have), std::greater<int>());
std::vector<std::pair<int, int>> ans;
while(len(have)) {
//每次取出为合法数中最小的数
int now = have.back();
//查找这个数的位置
int idx = find[now];
have.pop_back();
if(now == idx) {
//已经在之前的交换过程中变得合法了
continue;
}
//把值为now的数放在now位置上,把now位置上的数放在idx位置上
ans.push_back({now, idx});
find[a[now]] = idx;
find[a[idx]] = now;
std::swap(a[now], a[idx]);
}
if(len(ans)) {
std::cout << len(ans) << endl;
for(int i = 0; i < len(ans); i++) {
std::cout << ans[i].first << ' ' << ans[i].second << endl;
}
} else {
std::cout << 0;
}
return 0;
}
D - New Friends
问题描述
有一个由 \(N\) 用户使用的 SNS,标记为从 \(1\) 到 \(N\) 的数字。
在这个SNS中,两个用户可以互相成为朋友。
友谊是双向的;如果用户 X 是用户 Y 的朋友,则用户 Y 始终是用户 X 的朋友。
目前,SNS 上有 \(M\) 对好友,其中第 \(i\) 对由用户 \(A i\) 和 \(B i\) 组成。
确定以下操作可以执行的最大次数:
- 操作:选择三个用户X、Y、Z,其中X和Y是朋友,Y和Z是朋友,但X和Z不是。使 X 和 Z 成为朋友。
分析
一个简单图(图中没有自环和重边)那么它的最大边数为对于所有节点,两两节点间都有一条边
也就是 \(C(2, n)=n!/[2!\times(n - 2)!]=n\times(n-1)/2\) ,这就是\(n\)个节点的简单图的最大边数
我们可以利用这个性质,对于题目构建的图求连通块中的点数\(pointCnt\)和边数\(pathCnt\),该联通块提供的贡献就是 \(C(2, pointCnt)-pathCnt\)
代码
#include <bits/stdc++.h>
#define int long long
#define all(x) (x).begin(), (x).end()
#define len(x) (x).size()
#define endl '\n'
#define lowbit(x) ((x) & - (x))
//using namespace std;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
signed main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
//std::cout.precision(10);
int n, m;
std::cin >> n >> m;
std::vector<std::vector<int>> path(n + 1);
for(int i = 1; i <= m; i++) {
int u, v;
std::cin >> u >> v;
path[u].push_back(v);
path[v].push_back(u);
}
std::vector<int> f(n + 1);
int ans = 0;
std::map<std::pair<int,int>, int> flag;
auto dfs = [&](auto self, int now, int fa, int& path_cnt) -> int {
int point = 1;
f[now] = 1;
for(auto it : path[now]) {
if(!flag[{now, it}]) {
path_cnt++;
flag[{now, it}] = 1;
flag[{it, now}] = 1;
}
if(it == fa || f[it])
continue;
point += self(self, it, now, path_cnt);
}
return point;
};
for(int i = 1; i <= n; i++) {
if(!f[i]) {
int path_cnt = 0;
int point_cnt = dfs(dfs, i, -1, path_cnt);
if(point_cnt & 1) {
ans += (point_cnt - 1) / 2ll * point_cnt - path_cnt;
} else {
ans += point_cnt * (point_cnt - 1) / 2ll - path_cnt;
}
}
}
std::cout << ans;
return 0;
}
本文来自博客园,作者:独陷泥沼,感谢您的转载,创作不易,请注明原文链接:https://www.cnblogs.com/hyf-9134/articles/18151708

浙公网安备 33010602011771号