A. Attach 00

因为 \(100K\) 满足条件,所以最多暴力枚举 \(100\) 个即可。

B. Adjacent Tiles

因为目标是最小化暴露在外部的边数,所以也就是最小化图形的周长。假设整体可以容纳在一个 \(a \times b\) 的长方形中,周长为 \(2a+2b\),因此对于满足 \(a+b \ge n\)\(a\)\(b\),需要最小化 \(a+b\)。我们只需要考虑 \(\vert{}a-b\vert{} \le 1\) 的情况。

C. Ascending Labels

\(\text{DFS}\) 树上的深度满足条件。

D. Angst for All Pairs

按降序排列,并从 \(\text{popcount}\) 较小的开始使用。

E. ABC|AB|A

假设只能进行 \(A \to \varepsilon\)\(AB \to D\)\(D \to \varepsilon\)\(DC \to \varepsilon\) 的重写操作。我们需要维护一个仅存放 \(A\)\(D\) 的栈,从头开始遍历字符串 \(S\)。每当 \(B\)\(C\) 无法被消除时,就更新答案。

还有一个更简单的做法:

可删子串为 "A"、"AB"、"ABC"。把字符串反转后,这三种删除对应的后缀是 "A"、"BA"、"CBA"。因此可以反过来从左向右在线维护一个栈,遇到可删的后缀就立即删除。

代码实现
void solve() {
    string s;
    cin >> s;
    
    ranges::reverse(s);
    
    string t;
    for (char c : s) {
        t += c;
        char nc = 'A';
        while (t.size() and t.back() == nc) {
            t.pop_back();
            nc++;
        }
    }
    
    cout << t.size() << '\n';
}

F. AND/OR

虽然可以通过从高位到低位依次判定是否能置 1 来确定 \(M\),但深入思考这个判定就会发现,最终末尾 \(K\) 项的 \(\text{OR}\) 结果即为 \(M\)。我们可以从末尾开始,顺次考虑是选择 \(\text{OR}\) 还是 \(\text{AND}\) 。在不得不选 \(\text{OR}\) 的情况下很简单;而在 \(\text{OR}\)\(\text{AND}\) 都可以选的情况下,如果选择了 \(\text{OR}\),所有位都会满足条件,此时剩余 \(\text{AND/OR}\) 的抉择方式可以表示为二项式系数之和 \(\sum\limits_{i \le b} \binom{a}{i} := f(a, b)\)。我们要计算的 \(f(a, b)\) 如果倒过来看的话,\(a\)\(b\) 都是非递减的,因此这就变成了类似于莫队的转移中只进行指针增加的情况,总时间复杂度为 \(O(N)\)