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}\) 树中这两个字符串的终止节点之间的最短路