Codeforces Round 976 (Div. 2)

Aderose_yr發表於2024-10-03

C. Bitwise Balancing (C)

先求出 \(b - c\) 的值,再考慮 \(a\) 的每個二進位制位取0或1對答案的影響。vp的時候不知道為什麼錯了很多次。

void solve() {
    ll b, c, d;
    scanf("%lld%lld%lld", &b, &c, &d);
    if(b - c > d) {
        printf("-1\n");
        return;
    }
    ll x = d - (b - c), cst = 0;
    for(int r = 0; r < 61; r++) {
        ll y = 1ll << r;
        if((y & b) == 0 && (y & c)) cst |= y;
    }
    x -= cst;
    if(x < 0) {
        printf("-1\n");
        return;
    }
    ll add = 0, sub = 0;
    for(int r = 0; r <= 61; r++) {
        ll y = 1ll << r;
        if((y & b) == 0 && (y & c) == 0) add |= y;
        else if((y & b) && (y & c)) add |= y, sub |= y;
    }
    if((x & add) == x && (x ^ sub) <= (1ll << 61)) printf("%lld\n", x ^ sub);
    else printf("-1\n");
}

D. Connect the Dots (D)

注意到 \(d \leq 10\),用10個並查集儲存連邊操作為 \(d_i\) 時的連通情況,同時維護每個並查集的右端點,每次從當前並查集最右側開始遍歷,可避免 \(d_i\) 相同時、對同一個點多次操作導致TLE. 最後合併每層的資訊即可。

const int N = 2e5 + 10;
int f[12][N], r[12][N];
int find(int id, int i) {
    if(f[id][i] == i) return i;
    return f[id][i] = find(id, f[id][i]);
}
void merge(int id, int x, int y) {
    int fx = find(id, x), fy = find(id, y);
    f[id][fy] = fx;
    r[id][fx] = max(r[id][fx], r[id][fy]);
}
void solve() {
    int n, m;
    scanf("%d%d", &n, &m);
    for(int i = 0; i <= 10; i++) {
        for(int j = 1; j <= n; j++) {
            r[i][j] = f[i][j] = j;
        }
    }
    while(m--) {
        int a, d, k;
        scanf("%d%d%d", &a, &d, &k);
        if(find(d, a) != find(d, a + d * k)) {
            for(int i = a + d;;) {
                merge(d, a, i);
                if(find(d, a) == find(d, a + d * k)) break;
                int x = r[d][find(d, i)];
                i = x + d;
            }
        }
    }
    for(int i = 1; i <= 10; i++) {
        for(int j = 1; j <= n; j++) {
            int fa = find(i, j);
            if(fa != j) merge(0, j, fa);
        }
    }
    int cnt = 0;
    for(int i = 1; i <= n; i++) {
        if(f[0][i] == i) cnt++;
    }
    printf("%d\n", cnt);
}

E. Expected Power (E)

\(f(s)^2 = \sum\limits_{i = 0} ^ 9 \sum\limits_{j = 0} ^ 9 b_ib_j \times 2^{i + j}\),對每個二進位制位,\(b_i\)\(b_j\) 最多有4種不同的組合,維護每位每種情況的機率即可求得期望。

void solve() {
    int n;
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
    }
    ll b = inv(10000);
    memset(dp, 0, sizeof(dp));
    for(int i = 1; i <= n; i++) {
        int p;
        scanf("%d", &p);
        p1[i] = p * b % mo;
        p0[i] = (1 - p1[i] + mo) % mo;
    }
    for(int i = 0; i < 10; i++) {
        for(int j = 0; j < 10; j++) {
            dp[i][j][0][0] = 1;
        }
    }
    for(int i = 1; i <= n; i++) {
        for(int j = 0; j < 10; j++) {
            for(int k = 0; k < 10; k++) {
                int t1 = (a[i] >> j) & 1, t2 = (a[i] >> k) & 1;
                ll tmp[2][2];
                for(int p : {0, 1}) {
                    for(int q : {0, 1}) {
                        tmp[p][q] = dp[j][k][p][q] * p0[i] % mo + dp[j][k][p ^ t1][q ^ t2] * p1[i] % mo;
                        if(tmp[p][q] >= mo) tmp[p][q] -= mo;
                    }
                }
                for(int p : {0, 1}) {
                    for(int q : {0, 1}) {
                        dp[j][k][p][q] = tmp[p][q];
                    }
                }
            }
        }
    }
    ll ans = 0;
    for(int i = 0; i < 10; i++) {
        for(int j = 0; j < 10; j++) {
            ans += dp[i][j][1][1] * (1 << i + j) % mo;
            if(ans >= mo) ans -= mo;
        }
    }
    printf("%lld\n", ans);
}

F還沒補

相關文章