CF2020E. Expected Power

原题链接

前言

不是 \(\Theta (1024 \times n)\) 真能水过去?
So what's the point of allowing \(\Theta (1024 \times n)\) solutions to E????

算法

动态规划, 期望.

思路

读题, 发现 \(1 \le a_i \le 1023\).

这说明什么? 说明异或后的值一定 \(\le 1023\) !.

定义 \(f_{i,j}\) 表示前 \(i\) 个数中, 选出来的数按位异或的值为 \(j\) 的概率.

那么便可以十分平凡地进行转移, 枚举每个数取或者不取.

时间复杂度 \(\Theta (1024 \times n)\), 时限给的 4s, 完全够了.

#pragma GCC optimize("Ofast")

#include "iostream"

using namespace std;

const int N = 2e5 + 10, M = 1e3 + 50, mod = 1e9 + 7;

#define int long long

int n;
int a[N], p[N];
int f[2][M];

int qpow(int x, int y)
{
    int ret = 1;
    for (; y; y >>= 1, x = x * x % mod)
        if (y & 1)
            ret = ret * x % mod;
    return ret;
}

void init()
{
    cin >> n;
#pragma GCC unroll 8
    for (int i = 1; i <= n; ++i)
        cin >> a[i];
#pragma GCC unroll 8
    for (int i = 1; i <= n; ++i)
        cin >> p[i], p[i] = p[i] * qpow(1e4, mod - 2) % mod;
    return;
}

void calculate()
{
    for (int i = 0; i ^ 1024; ++i)
        f[0][i] = f[1][i] = 0;
    f[0][0] = 1;
    int nw = 1;
#pragma GCC unroll 8
    for (int i = 1; i <= n; ++i)
    {
        int p1 = p[i] % mod, p2 = (1 - p1 + mod) % mod;
        for (int j = 0; j ^ 1024; ++j)
            f[nw][j] = f[nw ^ 1][j] * p2 % mod;
        for (int j = 0; j ^ 1024; ++j)
            f[nw][j ^ a[i]] = (f[nw][j ^ a[i]] + f[nw ^ 1][j] * p1) % mod;
        nw ^= 1;
    }
    int ans = 0;
    for (int i = 0; i ^ 1024; ++i)
        ans = (ans + f[nw ^ 1][i] * i * i % mod) % mod;
    cout << ans << '\n';
}

void solve()
{
    init();
    calculate();
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int T;
    cin >> T;
    while (T--)
        solve();
    return 0;
}
posted @ 2024-12-07 11:44  Steven1013  阅读(17)  评论(0)    收藏  举报