A题:
思路:我们只需要后面的数字就行了,所以我弄了cnt=3,让前面三个字符不做任何操作,之后对后面的数字进行判断即可。
// Problem: A - Past ABCs
// Contest: AtCoder - AtCoder Beginner Contest 350
// URL: https://atcoder.jp/contests/abc350/tasks/abc350_a
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
//
#include <bits/stdc++.h>
using namespace std;
int main() {
int cnt = 3;
while (cnt -- ) {
char c; cin >> c;
}
bool ok = true;
int x; cin >> x;
if (x == 316) ok = false;
if (x < 1 || x > 349) ok = false;
if (ok) cout << "Yes\n";
else cout << "No\n";
return 0;
}
B题:
如果一个数出现奇数次,我们就帮他把牙齿拔掉。
简单利用下异或进行操作。
// Problem: B - Dentist Aoki
// Contest: AtCoder - AtCoder Beginner Contest 350
// URL: https://atcoder.jp/contests/abc350/tasks/abc350_b
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
//
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, q; cin >> n >> q;
vector<int> cnt(n + 1);
while (q -- ) {
int x; cin >> x;
cnt[x] ^= 1;
}
int ans = 0;
for (int i = 1; i <= n; i ++ )
if (cnt[i] == 1)
ans ++;
cout << n - ans << endl;
return 0;
}
C题:
模拟排序,我们用一个map存一个值所在的位置。
然后O(n)扫一遍,如果i的位置上就是i,那么continue
否则就把应该在i位置上的数交换过来。
过程是
a[id[i]] = a[i],i位置上的数不符合,交换到后面去
id[a[i]] = id[i],更新a[i]值在的位置到id[i]上
// Problem: C - Sort
// Contest: AtCoder - AtCoder Beginner Contest 350
// URL: https://atcoder.jp/contests/abc350/tasks/abc350_c
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
//
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
int main() {
int n; cin >> n;
vector<int> a(n + 1);
map<int, int> id;
for (int i = 1; i <= n; i ++ ) {
cin >> a[i];
id[a[i]] = i;
}
vector<PII> res;
for (int i = 1; i <= n; i ++ ) {
if (id[i] == i) continue;
res.push_back({i, id[i]});
id[a[i]] = id[i];
a[id[i]] = a[i];
}
cout << res.size() << endl;
for (auto &[l, r] : res) cout << l << ' ' << r << endl;
return 0;
}
D题:
对于样例一:
4 3
1 2
2 3
1 4
这是他们的关系
4 -- 1 -- 2 -- 3
1可以和3通过2建立关系,2可以通过1和4建立关系,3可以通过2和1建立关系。
最终形成的关系网络就是完全图,最终边数为(tot - 1) * tot / 2
所以我们用到了并查集。
如果是好朋友,但是不在同一个块里,合到同一个块中。
否则最终可以贡献的边数 --。
// Problem: D - New Friends
// Contest: AtCoder - AtCoder Beginner Contest 350
// URL: https://atcoder.jp/contests/abc350/tasks/abc350_d
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
//
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 2e5 + 9;
int p[N], s[N], cnt[N];
int find(int x) {
return p[x] == x ? x : p[x] = find(p[x]);
}
int main() {
int n, m; cin >> n >> m;
for (int i = 1; i <= n; i ++ ) {
p[i] = i, s[i] = 1;
}
while (m -- ) {
int u, v; cin >> u >> v;
int f1 = find(u), f2 = find(v);
if (f1 == f2) {
cnt[f1] ++;
}else {
p[f1] = f2;
s[f2] += s[f1];
cnt[f2] += cnt[f1];
}
}
ll res = 0;
for (int i = 1; i <= n; i ++ ) {
if (find(i) == i) {
res += 1ll * s[i] * (s[i] - 1) / 2 - (s[i] - 1) - cnt[i];
}
}
cout << res << endl;
return 0;
}
E题:
记f(n)为变成0所需的最小花费
用方法1:
f(n) = f(n / a) + x
用方法2:
f(n) = (f(n) + Y) / 6 + (f(n / b) + Y) / 6
// Problem: E - Toward 0
// Contest: AtCoder - AtCoder Beginner Contest 350
// URL: https://atcoder.jp/contests/abc350/tasks/abc350_e
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
//
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
ll n, a, x, y;
unordered_map<ll, double> f;
double dp(ll n) {
if (n == 0) return 0;
if (f.count(n)) return f[n];
double sum = y;
for (int i = 2; i <= 6; i ++ ) {
sum += dp(n / i) + y;
}
sum /= 5;
f[n] = min(sum, dp(n / a) + x);
return f[n];
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin >> n >> a >> x >> y;
printf("%.8lf\n", dp(n));
return 0;
}