CF2020E Expected Power题解

这场 Div2 有点简单了,\(47\text{min}\) 过了 \(5\) 题,\(rk\text{12}\)

经典的,由于此题要求 \(E(f(S)^2)\),考虑拆成两位然后求期望的和,于是先枚举拆成哪两位,然后问题转换成要求最终两个位上的结果以及对应概率,动态规划,设 \(f_{i,0/1,0/1}\) 表示当前处理了前 \(i\) 个数,这两位分别是 \(0/1\) 的概率,转移考虑 \(i\) 这个数选或者不选即可,复杂度 \(n\log^2 n\)

代码:

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 200200, M = 10, mod = 1e9 + 7;
int T, n, ret;
int a[N], p[N];
int qow(int a, int b) {
    int ans = 1;
    while (b) {
        if (b & 1) ans = ans * a % mod;
        b >>= 1, a = a * a % mod;
    }
    return ans;
}
int s[2][2], g[2][2];
int calc(int i, int j) {
    s[0][0] = 1, s[1][0] = s[0][1] = s[1][1] = 0;
    for (int o = 1; o <= n; ++o) {
        int ii = (a[o] >> i) & 1, jj = (a[o] >> j) & 1;
        g[0][0] = s[0][0], s[0][0] = 0;
        g[0][1] = s[0][1], s[0][1] = 0;
        g[1][0] = s[1][0], s[1][0] = 0;
        g[1][1] = s[1][1], s[1][1] = 0;
        for (int p1 = 0; p1 < 2; ++p1) {
            for (int p2 = 0; p2 < 2; ++p2) {
                s[p1][p2] = (s[p1][p2] + (mod + 1 - p[o]) * g[p1][p2]) % mod;
                s[p1 ^ ii][p2 ^ jj] = (s[p1 ^ ii][p2 ^ jj] + p[o] * g[p1][p2]) % mod;
            }
        }
    }
    return s[1][1] * qow(2, i + j) % mod;
}
void solve() {
    scanf("%lld", &n), ret = 0;
    for (int i = 1; i <= n; ++i) scanf("%lld", a + i);
    for (int i = 1, x; i <= n; ++i) scanf("%lld", &x), p[i] = x * qow(10000, mod - 2) % mod;
    for (int i = 0; i < M; ++i)
        for (int j = 0; j < M; ++j)
            ret = (ret + calc(i, j)) % mod;
    printf("%lld\n", ret);
    return;
}
signed main() {
    scanf("%lld", &T);
    while (T--) solve();
    return 0;
}
posted @ 2024-10-12 21:21  yaoyanfeng  阅读(18)  评论(0)    收藏  举报