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;
}

浙公网安备 33010602011771号