Codeforces Round 911 (Div. 2)补题C、D

发布时间 2023-11-28 23:03:39作者: jvdyvan

Codeforces Round 911 (Div. 2)

C. Anji's Binary Tree

思路

树形dp

ac代码

#include <bits/stdc++.h>

using namespace std;
using i64  = long long;
const i64 inf = 8e18;
typedef pair<int, int> pii;
const int N = 3e5 + 10;

char w[N];//存U、L、R
int ls[N], rs[N];//存左孩子,右孩子

int dfs(int u) {
    if (!ls[u] && !rs[u]) return 0;
    int res = N;
    if (ls[u]) res = min(res, f(ls[u]) + (w[u] != 'L'));
    if (rs[u]) res = min(res, f(rs[u]) + (w[u] != 'R'));
    return res;
}

void solve() {
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> w[i];
    for (int i = 1; i <= n; i++) cin >> ls[i] >> rs[i];

    cout << dfs(1) << endl;
}

int main() {
    ios::sync_with_stdio(0); cin.tie(0);

    int t = 1;
    cin >> t;
    while (t --) solve();

    return 0;
}

D. Small GCD

思路

题目要求输出的是数组中的每对\((i, j, k)\)\(f(a_i,a_j,a_k)\),所以我们可以先给数组按从小到大排个序。我们意识到:\(f(a_i,a_j,a_k)\)的值和\(a_i,a_j,a_k\)最大的数是无关的。我们假设\(a_k\)是这三个数里最小的,\(a_i\)是第二小,固定\(a_i\)\(a_j\),则\(a_k\)的取值有\(n - i\)个。
开一个b数组,\(b_i\)里存\(i\)的所以因子;再开一个c数组\(c_i\)表示因子i的的出现次数;再开一个f数组,\(f_i\)表示gcd(x, y) == i 的倍数的数对个数。容斥一下得到,gcd(x, y) == i 的数对个数等于\(f_i\) - \(f_2\)\(_i\) - \(f_3\)\(_i\) - \(f_4\)\(_i\) ... - \(f_x\)\(_i\)\(x * i\) <= 最大的因子

ac代码

#include <bits/stdc++.h>

using namespace std;
using i64  = long long;
const i64 inf = 8e18;
typedef pair<int, int> pii;
const int N = 3e5 + 10;

vector<int> b[100010];

void solve() {
    int n;
    cin >> n;
    vector<i64> a(n + 1), c(N), f(N);
    for (int i = 1; i <= n; i++) cin >> a[i];
    sort(a.begin() + 1, a.end());
    for (int i = 1; i <= n; i++) {
        for (auto x : b[a[i]]) {
            f[x] += c[x] * (n - i);
            c[x] ++;
        }
    }
    i64 ans = 0;
    for (int i = 100000; i > 0; i--) {
        for (int j = i + i; j <= 100000; j += i) {
            f[i] -= f[j];
        }
        ans += f[i] * i;
    }

    cout << ans << endl;
}

int main() {
    ios::sync_with_stdio(0); cin.tie(0);

    for (int i = 1; i <= 100000; i++) {
        for (int j = i; j <= 100000; j += i)
            b[j].push_back(i);
    }

    int t = 1;
    cin >> t;
    while (t --) solve();

    return 0;
}