A. Shuffled Equation

排序

代码实现
a, b, c = sorted(map(int, input().split()))
if a*b == c:
    print('Yes')
else:
    print('No')

B. Who is Missing?

模拟

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

using namespace std;

int main() {
    int n, m;
    cin >> n >> m;
    
    vector<int> a(m);
    rep(i, m) cin >> a[i];
    
    vector<int> ans;
    for (int i = 1; i <= n; ++i) {
        bool exist = false;
        for (int na : a) if (na == i) exist = true;
        if (!exist) ans.push_back(i);
    }
    
    cout << ans.size() << '\n';
    for (int x : ans) cout << x << ' ';
    
    return 0;
}

C. Bib

答案为 \(Q(P(Q^{-1}(i)))\)

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

using namespace std;

int main() {
    int n;
    cin >> n;
    
    vector<int> p(n), q(n);
    rep(i, n) cin >> p[i], p[i]--;
    rep(i, n) cin >> q[i], q[i]--;
    
    vector<int> r(n);
    rep(i, n) r[q[i]] = i;
    
    rep(i, n) {
        int x = r[i];
        x = p[x];
        x = q[x];
        cout << x+1 << ' ';
    }
    
    return 0;
}

D. Doubles

可以用哈希预处理出 \(a_j\) 序列中每种数的个数,这样对于任意两个骰子就能做到 \(O(K_i+K_j)\),总复杂度为 \(O(NM)\)

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

using namespace std;

int main() {
    int n;
    cin >> n;
    
    vector<int> k(n);
    vector<vector<int>> a(n);
    rep(i, n) {
        cin >> k[i];
        a[i].resize(k[i]);
        rep(j, k[i]) cin >> a[i][j];
    }
    
    double ans = 0;
    rep(i, n)rep(j, i) {
        double now = 0;
        
        unordered_map<int, int> cnt;
        for (int na : a[j]) cnt[na]++;
        
        for (int na : a[i]) now += cnt[na];
        now /= k[i];
        now /= k[j];
        
        ans = max(ans, now);
    }
    
    printf("%.10f\n", ans);
    
    return 0;
}

E. Cables and Servers

显然答案是连通分量的个数减一
操作就是将重边和自环连向其他连通块

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

using namespace std;

int main() {
    int n, m;
    cin >> n >> m;
    
    int ans = n-1;
    dsu uf(n);
    vector<tuple<int, int, int>> es;
    rep(i, m) {
        int a, b;
        cin >> a >> b;
        --a; --b;
        if (uf.same(a, b)) {
            es.emplace_back(i, a, b);
        }
        else {
            uf.merge(a, b);
            ans--;
        }
    }
    
    cout << ans << '\n';
    int v = 0;
    rep(i, ans) {
        auto [ei, a, b] = es.back(); es.pop_back();
        while (uf.same(v, a)) v++;
        uf.merge(a, v);
        printf("%d %d %d\n", ei+1, a+1, v+1);
    }
    
    return 0;
}

F. Insert

倒过来考虑
那么只需将当前数填在剩下没填的位置里的第 \(P_i\) 个位置
可以用树状数组或线段树上二分来实现,复杂度为 2只log 或 1只log

当然也可以直接上平衡树

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

using namespace std;

template<typename T=int>
struct BIT {
  int n;
  vector<T> d;
  BIT(int _n=0) {
      n = 1;
      while (n <= _n+1) n <<= 1;
      d.resize(n);
  }
  void add(int i, T x=1) {
    for (i++; i <= n; i += i&-i) {
      d[i] += x;
    }
  }
  T sum(int i) {
    T x = 0;
    for (i++; i; i -= i&-i) {
      x += d[i];
    }
    return x;
  }
  T sum(int l, int r) {
    return sum(r-1) - sum(l-1);
  }
  int getKth(int k) {
      int w = n, i = 0;
      while (w) {
          if (k > d[i+w]) i += w, k -= d[i];
          w >>= 1;
      }
      return i;
  }
};

int main() {
    int n;
    cin >> n;
    
    vector<int> p(n);
    rep(i, n) cin >> p[i];
    
    BIT d(n);
    rep(i, n) d.add(i);
    
    vector<int> ans(n);
    for (int i = n-1; i >= 0; --i) {
        int j = d.getKth(p[i]);
        ans[j] = i+1;
        d.add(j, -1);
    }
    
    rep(i, n) cout << ans[i] << ' ';
    
    return 0;
}

G. Fine Triplets

\(A+C=2B\),可以枚举 \(2B\),然后用 \(\operatorname{FFT}\) 来统计满足条件的 \((A, C)\) 的个数即可,时间复杂度为 \(\mathcal{O}(N\log N)\)

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

using namespace std;
using ll = long long;

int main() {
    int n;
    cin >> n;
    
    const int MX = 1000001;
    vector<int> a(MX);
    vector<int> s(n);
    rep(i, n) {
        cin >> s[i];
        a[s[i]]++;
    }
    
    auto ac = convolution(a, a);
    for (int x : s) ac[x*2]--;
    rep(i, ac.size()) ac[i] /= 2;
    
    ll ans = 0;
    for (int x : s) ans += ac[x*2];
    cout << ans << '\n';
    
    return 0;
}