A. Rearranging ABC
排序
代码实现
s = input()
if ''.join(sorted(s)) == 'ABC':
print('Yes')
else:
print('No')
B. Avoid Rook Attack
模拟
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
int main() {
int n = 8;
vector<string> s(n);
rep(i, n) cin >> s[i];
int ans = 0;
rep(i, n)rep(j, n) {
if (s[i][j] == '#') continue;
bool ok = true;
rep(k, n) if (s[i][k] == '#') ok = false;
rep(k, n) if (s[k][j] == '#') ok = false;
if (ok) ans++;
}
cout << ans <<'\n';
return 0;
}
C. Avoid Knight Attack
可以用 std::set
来维护每个可以被攻击到的位置以及当前被占领的位置
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
using P = pair<int, int>;
const int di[] = {2, 1, -1, -2, -2, -1, 1, 2, 0};
const int dj[] = {1, 2, 2, 1, -1, -2, -2, -1, 0};
int main() {
int n, m;
cin >> n >> m;
set<P> st;
rep(i, m) {
int a, b;
cin >> a >> b;
rep(v, 9) {
int na = a+di[v], nb = b+dj[v];
if (na < 1 or nb < 1 or na > n or nb > n) continue;
st.emplace(na, nb);
}
}
ll ans = (ll)n*n;
ans -= st.size();
cout << ans << '\n';
return 0;
}
D. Many Segments 2
双指针
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
int main() {
int n, m;
cin >> n >> m;
vector<int> maxL(m+1, -1);
rep(i, n) {
int l, r;
cin >> l >> r;
maxL[r] = max(maxL[r], l);
}
ll ans = 0;
int l = 1;
for (int r = 1; r <= m; ++r) {
while (l <= maxL[r]) ++l;
ans += r-l+1;
}
cout << ans << '\n';
return 0;
}
E. Permute K times 2
答案就是对每个 \(i\) 做 \(p^{2^k}\) 的变换
可以分解成若干个置换环,然后对每个置换环做 \(2^k \bmod\) 其环长 \(c\) 次操作即可
加强版:P7981
代码实现
#include <bits/stdc++.h>
#if __has_include(<atcoder/all>)
#include <atcoder/all>
using namespace atcoder;
#endif
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
int main() {
int n; ll k;
cin >> n >> k;
vector<int> p(n);
rep(i, n) cin >> p[i];
rep(i, n) p[i]--;
vector<int> ans(n);
vector<bool> used(n);
rep(i, n) if (!used[i]) {
int v = i;
vector<int> vs;
while (!used[v]) {
used[v] = true;
vs.push_back(v);
v = p[v];
}
int c = vs.size();
int m = pow_mod(2, k, c);
rep(i, c) {
ans[vs[i]] = vs[(i+m)%c];
}
}
rep(i, n) cout << ans[i]+1 << ' ';
return 0;
}
F. Avoid Queen Attack
容斥原理
把攻击范围分成横竖斜 \(4\) 来考虑的话,总的攻击格子数马上就能知道。被至少 \(2\) 种方式攻击的格子只有 \(O(M^2)\) 个,全部枚举出来去掉重复的即可。
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
using P = pair<int, int>;
int main() {
int n, m;
cin >> n >> m;
set<int> X, Y, S, D;
rep(i, m) {
int a, b;
cin >> a >> b;
--a; --b;
X.insert(a);
Y.insert(b);
S.insert(a+b);
D.insert(a-b);
}
ll ans = (ll)n*n;
for (int x : X) ans -= n;
for (int y : Y) ans -= n;
for (int s : S) ans -= n - abs(s-(n-1));
for (int d : D) ans -= n - abs(d);
map<P, int> cnt;
auto add = [&](int x, int y) {
if (x < 0 or y < 0 or x >= n or y >= n) return;
cnt[P(x, y)]++;
};
for (int x : X)for (int y : Y) add(x, y);
for (int x : X)for (int s : S) add(x, s-x);
for (int x : X)for (int d : D) add(x, x-d);
for (int y : Y)for (int s : S) add(s-y, y);
for (int y : Y)for (int d : D) add(y+d, y);
for (int s : S)for (int d : D) {
if ((s+d)%2) continue;
add((s+d)/2, (s-d)/2);
}
for (auto [p, num] : cnt) {
if (num == 1) ans += 1;
if (num == 3) ans += 2;
if (num == 6) ans += 3;
}
cout << ans << '\n';
return 0;
}
G. Edit to Match
可以对 \(\operatorname{Trie}\) 树进行改造
将 \(S_i\) 变成 \(S_j\) 的最小操作次数就是在 \(\operatorname{Trie}\) 树中这两个字符串的终止节点之间的最短路