E. Expected Power
E. Expected Power
You are given an array of integers . You are also given an array .
Let denote the random multiset (i. e., it may contain equal elements) constructed as follows:
- Initially, is empty.
- For each from to , insert into with probability . Note that each element is inserted independently.
Denote as the bitwise XOR of all elements of . Please calculate the expected value of . Output the answer modulo .
Formally, let . It can be shown that the answer can be expressed as an irreducible fraction , where and are integers and . Output the integer equal to . In other words, output such an integer that and .
Input
Each test contains multiple test cases. The first line contains the number of test cases (). The description of the test cases follows.
The first line of each test case contains a single integer ().
The second line of each test case contains integers ().
The third line of each test case contains integers ().
It is guaranteed that the sum of over all test cases does not exceed .
Output
For each test case, output the expected value of , modulo .
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, and each element is inserted into with probability , since and . Thus, there are outcomes for , each happening with the same probability of :
- . In this case, , .
- . In this case, , .
- . In this case, , .
- . In this case, , .
Hence, the answer is .
In the second test case, , is inserted into with probability , while is inserted into with probability . There are outcomes for :
- . In this case, , . This happens with probability .
- . In this case, , . This happens with probability .
- . In this case, , . This happens with probability .
Hence, the answer is .
解题思路
由于 ,因此有 (这里的 表示集合内元素的异或值)。一种求期望的做法是分别求出每个 对应的 的期望再求和,也就是 ,其中 表示异或结果等于 的概率。
可以通过简单的 dp 求得。定义 表示从前 个数中选出异或结果为 的集合的概率,根据是否选择第 个数进行状态转移,有状态转移方程 。
最后要求的期望就是 。
AC 代码如下,时间复杂度为 :
#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;
}
实际上是因为 的值域太小所以才放过上面的暴力做法,下面给出正解。
如果单纯求的是 的期望,我们容易想到拆位然后分别考虑每一位对期望的贡献。 也是可以这样做的,有
所以现在我们需要求出每个 的概率是多少,记为 ,那么所求期望就是 。而 同样可以用 dp 求得。
定义 表示从前 个数中选出异或结果的二进制的第 位为 且第 位为 的集合的概率,一样根据是否选择第 个数进行状态转移,状态转移方程就是 ,其中 表示 的二进制第 位的值。
最后要求的期望就是 。
AC 代码如下,时间复杂度为 :
#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
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/18449808
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
2023-10-07 D. Prefix Purchase