E. Expected Power

E. Expected Power

You are given an array of n integers a1,a2,,an. You are also given an array p1,p2,,pn.

Let S denote the random multiset (i. e., it may contain equal elements) constructed as follows:

  • Initially, S is empty.
  • For each i from 1 to n, insert ai into S with probability pi104. Note that each element is inserted independently.

Denote f(S) as the bitwise XOR of all elements of S. Please calculate the expected value of (f(S))2. Output the answer modulo 109+7.

Formally, let M=109+7. It can be shown that the answer can be expressed as an irreducible fraction pq, where p and q are integers and q0(modM). Output the integer equal to pq1modM. In other words, output such an integer x that 0x<M and xqp(modM).

Input

Each test contains multiple test cases. The first line contains the number of test cases t (1t104). The description of the test cases follows.

The first line of each test case contains a single integer n (1n2105).

The second line of each test case contains n integers a1,a2,,an (1ai1023).

The third line of each test case contains n integers p1,p2,,pn (1pi104).

It is guaranteed that the sum of n over all test cases does not exceed 2105.

Output

For each test case, output the expected value of (f(S))2, modulo 109+7.

Example

Input

4
2
1 2
5000 5000
2
1 1
1000 2000
6
343 624 675 451 902 820
6536 5326 7648 2165 9430 5428
1
1
10000

Output

500000007
820000006
280120536
1

Note

In the first test case, a=[1,2] and each element is inserted into S with probability 12, since p1=p2=5000 and pi104=12. Thus, there are 4 outcomes for S, each happening with the same probability of 14:

  • S=. In this case, f(S)=0, (f(S))2=0.
  • S={1}. In this case, f(S)=1, (f(S))2=1.
  • S={2}. In this case, f(S)=2, (f(S))2=4.
  • S={1,2}. In this case, f(S)=12=3, (f(S))2=9.

Hence, the answer is 014+114+414+914=144=72500000007(mod109+7).

In the second test case, a=[1,1], a1 is inserted into S with probability 0.1, while a2 is inserted into S with probability 0.2. There are 3 outcomes for S:

  • S=. In this case, f(S)=0, (f(S))2=0. This happens with probability (10.1)(10.2)=0.72.
  • S={1}. In this case, f(S)=1, (f(S))2=1. This happens with probability (10.1)0.2+0.1(10.2)=0.26.
  • S={1,1}. In this case, f(S)=0, (f(S))2=0. This happens with probability 0.10.2=0.02.

Hence, the answer is 00.72+10.26+00.02=0.26=26100820000006(mod109+7).

 

解题思路

  由于 1ai1023,因此有 S[0,1023](这里的 S 表示集合内元素的异或值)。一种求期望的做法是分别求出每个 S 对应的 S2 的期望再求和,也就是 S=01023PSS2,其中 PS 表示异或结果等于 S 的概率。

  PS 可以通过简单的 dp 求得。定义 f(i,j) 表示从前 i 个数中选出异或结果为 j 的集合的概率,根据是否选择第 i 个数进行状态转移,有状态转移方程 f(i,j)=f(i1,j)(1pi104)+f(i1,jai)pi104

  最后要求的期望就是 S=01023f(n,S)S2

  AC 代码如下,时间复杂度为 O(n2logA+1)

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

const int N = 2e5 + 5, M = 1 << 10, mod = 1e9 + 7;

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

void solve() {
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
    }
    for (int i = 1; i <= n; i++) {
        cin >> p[i];
    }
    memset(f[0], 0, sizeof(f[0]));
    f[0][0] = 1;
    for (int i = 1; i <= n; i++) {
        memset(f[i & 1], 0, sizeof(f[0]));
        for (int j = 0; j < M; j++) {
            f[i & 1][j] = ((10000 - p[i]) * 285700002ll % mod * f[i - 1 & 1][j] + p[i] * 285700002ll % mod * f[i - 1 & 1][j ^ a[i]]) % mod;
        }
    }
    int ret = 0;
    for (int i = 0; i < M; i++) {
        ret = (ret + 1ll * f[n & 1][i] * i % mod * i) % mod;
    }
    cout << ret << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t;
    cin >> t;
    while (t--) {
        solve();
    }
    
    return 0;
}

  实际上是因为 ai 的值域太小所以才放过上面的暴力做法,下面给出正解。

  如果单纯求的是 S 的期望,我们容易想到拆位然后分别考虑每一位对期望的贡献。S2 也是可以这样做的,有S2=(b929+b828++b020)2=i=09j=09bibj2i+j

  所以现在我们需要求出每个 bibj=1 的概率是多少,记为 Pi,j,那么所求期望就是 i=09j=09Pi,j2i+j。而 Pi,j 同样可以用 dp 求得。

  定义 f(i,j,k,u,v) (u,v{0,1}) 表示从前 i 个数中选出异或结果的二进制的第 j 位为 u 且第 k 位为 v 的集合的概率,一样根据是否选择第 i 个数进行状态转移,状态转移方程就是 f(i,j,k,u,v)=f(i1,j,k,u,v)(1pi104)+f(i1,j,k,uai,u,vai,v)pi104,其中 ai,j 表示 ai 的二进制第 j 位的值。

  最后要求的期望就是 i=09j=09f(n,i,j,1,1)2i+j

  AC 代码如下,时间复杂度为 O(nlog2A)

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

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

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

void solve() {
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
    }
    for (int i = 1; i <= n; i++) {
        cin >> p[i];
    }
    memset(f[0], 0, sizeof(f[0]));
    for (int i = 0; i < M; i++) {
        for (int j = 0; j < M; j++) {
            f[0][i][j][0][0] = 1;
        }
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 0; j < M; j++) {
            for (int k = 0; k < M; k++) {
                for (int u = 0; u <= 1; u++) {
                    for (int v = 0; v <= 1; v++) {
                        f[i & 1][j][k][u][v] = ((10000 - p[i]) * 285700002ll % mod * f[i - 1 & 1][j][k][u][v] + p[i] * 285700002ll % mod * f[i - 1 & 1][j][k][u ^ (a[i] >> j & 1)][v ^ (a[i] >> k & 1)]) % mod;
                    }
                }
            }
        }
    }
    int ret = 0;
    for (int i = 0; i < M; i++) {
        for (int j = 0; j < M; j++) {
            ret = (ret + (1ll << i + j) * f[n & 1][i][j][1][1]) % mod;
        }
    }
    cout << ret << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t;
    cin >> t;
    while (t--) {
        solve();
    }
    
    return 0;
}

 

参考资料

  Tutorial for Codeforces Round 976 (Div. 2) and Divide By Zero 9.0:https://codeforces.com/blog/entry/134516

posted @   onlyblues  阅读(107)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
历史上的今天:
2023-10-07 D. Prefix Purchase
Web Analytics
点击右上角即可分享
微信分享提示