A. 12435

模拟

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)

using namespace std;

int main() {
    int n = 5;
    vector<int> a(n);
    rep(i, n) cin >> a[i];
    
    rep(i, n-1) {
        swap(a[i], a[i+1]);
        if (ranges::is_sorted(a)) {
            puts("Yes");
            return 0;
        }
        swap(a[i], a[i+1]);
    }
    
    puts("No");
    
    return 0;
}

B. Geometric Sequence

可以利用 \(A_{i+1}^2 = A_i \times A_{i+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;
    cin >> n;
    
    vector<ll> a(n);
    rep(i, n) cin >> a[i];
    
    rep(i, n-2) {
        if (a[i+1]*a[i+1] != a[i]*a[i+2]) {
            puts("No");
            return 0;
        }
    }
    
    puts("Yes");
    
    return 0;
}

C. Paint to make a rectangle

模拟
判断包含所有黑色格子的最小矩形内是否还有白色格子

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)

using namespace std;

int main() {
    int h, w;
    cin >> h >> w;
    
    vector<string> s(h);
    rep(i, h) cin >> s[i];
    
    int li = h, ri = 0;
    int lj = w, rj = 0;
    rep(i, h)rep(j, w) if (s[i][j] == '#') {
        li = min(li, i); ri = max(ri, i);
        lj = min(lj, j); rj = max(rj, j);
    }
    
    for (int i = li; i <= ri; ++i) {
        for (int j = lj; j <= rj; ++j) {
            if (s[i][j] == '.') {
                puts("No");
                return 0;
            }
        }
    }
    
    puts("Yes");
    
    return 0;
}

D. Stone XOR

通过观察可以发现,这个操作实际上就是对序列分成若干个组(容易想到贝尔数)
\(B_{12}\) 大概在 \(4e6\) 左右,所以可以考虑爆搜
注意不要用 set 来去重

代码实现
#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;
    cin >> n;
    
    vector<ll> a(n);
    rep(i, n) cin >> a[i];
    
    vector<ll> xs;
    vector<vector<int>> groups;
    auto dfs = [&](auto f, int i) {
        if (i == n) {
            ll x = 0;
            rep(j, groups.size()) {
                ll sum = 0;
                for (int ni : groups[j]) {
                    sum += a[ni];
                }
                x ^= sum;
            }
            xs.push_back(x);
            return;
        }
        
        rep(j, groups.size()) {
            groups[j].push_back(i);
            f(f, i+1);
            groups[j].pop_back();
        }
        
        groups.push_back(vector<int>(1, i));
        f(f, i+1);
        groups.pop_back();
    };
    dfs(dfs, 0);
    
    ranges::sort(xs);
    xs.erase(unique(xs.begin(), xs.end()), xs.end());
    cout << xs.size() << '\n';
    
    return 0;
}

E. Vitamin Balance

看到最大化最小值,直接考虑二分答案
可以先对每种维他命的食物分别预处理出在不同的卡路里摄取限定下选若干个食物能得到的最大的 \(\sum A\),典型的01背包问题

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)

using namespace std;
using P = pair<int, int>;

inline void chmax(int& x, int y) { if (x < y) x = y; }

int main() {
    int n, x;
    cin >> n >> x;
    
    vector<vector<P>> foods(3);
    rep(i, n) {
        int v, a, c;
        cin >> v >> a >> c;
        --v;
        foods[v].emplace_back(a, c);
    }
    
    vector d(3, vector<int>(x+1));
    rep(v, 3) {
        vector<int> dp(x+1);
        for (auto [a, c] : foods[v]) {
            for (int i = x; i >= c; --i) {
                chmax(dp[i], dp[i-c]+a);
            }
        }
        d[v] = dp;
    }
    
    auto judge = [&](int r) {
        int tot = 0;
        rep(v, 3) {
            if (d[v][x] < r) return false;
            int need = ranges::lower_bound(d[v], r) - d[v].begin();
            tot += need;
        }
        return tot <= x;
    };
    
    int ac = 0, wa = 1001001001;
    while (abs(ac-wa) > 1) {
        int wj = (ac+wa)/2;
        if (judge(wj)) ac = wj; else wa = wj;
    }
    
    cout << ac << '\n';
    
    return 0;
}

F. Double Sum 3

\(f(l, r)\) 其实就是对区间 \([l, r]\) 中的数分成几个极大连续段,每段中的最大值\(+1\) 没有出现在区间中。意味着我们只需求出包含 \(x\) 但不包含 \(x+1\) 的区间数
对于 \(x=1, 2, \cdots, N\),我们可以通过求包含 \(x\)\(x+1\) 的区间数减去包含 \(x+1\) 的区间数,从而得到包含 \(x\) 但不包含 \(x+1\) 的区间数

代码实现
#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;
    cin >> n;
    
    vector<int> a(n);
    rep(i, n) cin >> a[i], a[i]--;
    
    vector<vector<int>> is(n+1);
    rep(i, n) is[a[i]].push_back(i);
    
    auto calc = [&](vector<int> is) {
        ll res = (ll)n*(n+1)/2;
        is.insert(is.begin(), -1);
        is.push_back(n);
        rep(j, is.size()-1) {
            int w = is[j+1]-is[j]-1;
            res -= (ll)w*(w+1)/2;
        }
        return res;
    };
    
    ll ans = 0;
    rep(i, n) {
        vector<int> nis = is[i];
        nis.insert(nis.begin(), is[i+1].begin(), is[i+1].end());
        ranges::sort(nis);
        ans += calc(nis) - calc(is[i+1]);
    }
    
    cout << ans << '\n';
    
    return 0;
}

G. Permutation Concatenation

还是考虑贡献
容易发现,对于相同位数的数需要乘的系数都是一样的,那么我们只需考虑对每种数位进行讨论贡献即可
最后的答案为 \(\displaystyle\sum\limits_{k'=1}^6\sum\limits_{i=1}^n [i \ \text{的位数} = k'] \times i \times \left(\sum_{j=0}^{n-1} \bigg([x^j]\dfrac{1}{(1+10^{k'}x)}\prod\limits_{k=1}^6 (1+10^kx)^{C_k}\bigg) \times j! \times (n-1-j)!\right)\)
其中,对于 \(\prod\limits_{k=1}^6 (1+10^kx)^{C_k}\) 这部分可以先用分治NTT预处理出来,\(C_k\) 表示 \(k\) 位数的个数

代码实现
#include <bits/stdc++.h>
#include <atcoder/all>
using namespace atcoder;
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define rep1(i, n) for (int i = 1; i <= (n); ++i)

using namespace std;
using mint = modint998244353;
using fps = vector<mint>;

struct modinv {
  int n; vector<mint> d;
  modinv(): n(2), d({0,1}) {}
  mint operator()(int i) {
    while (n <= i) d.push_back(-d[mint::mod()%n]*(mint::mod()/n)), ++n;
    return d[i];
  }
  mint operator[](int i) const { return d[i];}
} invs;
struct modfact {
  int n; vector<mint> d;
  modfact(): n(2), d({1,1}) {}
  mint operator()(int i) {
    while (n <= i) d.push_back(d.back()*n), ++n;
    return d[i];
  }
  mint operator[](int i) const { return d[i];}
} facts;
struct modfactinv {
  int n; vector<mint> d;
  modfactinv(): n(2), d({1,1}) {}
  mint operator()(int i) {
    while (n <= i) d.push_back(d.back()*invs(n)), ++n;
    return d[i];
  }
  mint operator[](int i) const { return d[i];}
} ifacts;
mint comb(int n, int k) {
  if (n < k || k < 0) return 0;
  return facts(n)*ifacts(k)*ifacts(n-k);
}

int main() {
    int n;
    cin >> n;
    
    vector<int> k(n+1);
    rep1(i, n) k[i] = to_string(i).size();
    vector<int> cnt(7);
    rep1(i, n) cnt[k[i]]++;
    
    vector<mint> ten(7, 1);
    rep(i, 6) ten[i+1] = ten[i]*10;
    
    fps f;
    {
        queue<fps> q;
        rep1(i, 6) {
            rep(j, cnt[i]) q.push(fps({1, ten[i]}));
        }
        while (q.size() > 1) {
            auto fa = q.front(); q.pop();
            auto fb = q.front(); q.pop();
            q.push(convolution(fa, fb));
        } 
        f = q.front();
    }
    
    mint ans;
    rep1(nk, 6) {
        auto _f = f;
        fps nf(n);
        rep(i, n) {
            nf[i] = _f[i];
            // _f[i] -= nf[i];
            _f[i+1] -= nf[i]*ten[nk];
        }
        mint co;
        rep(i, n) co += nf[i] * facts(i) * facts(n-1-i);
        rep1(i, n) if (k[i] == nk) ans += co*i;
    }
    
    cout << ans.val() << '\n';
    
    return 0;
}