E. Expected Power
在这里伤感一下思路都对了但是拆位拆错了的这一题,在看到这道题的第一眼,好原,但是又不怎么原。突然,我就想到了这一道题,同样是所有数两两异或的平方和,H. xor,但是这题是需要将所有子序列进行异或,求所有异或平方的和的期望,我当时就想到了直接将期望乘在每一个数字上,选择这位就乘
p
p
p,否则就乘
1
−
p
1-p
1−p。但是因为拆位没拆明白,导致最终还是没有做出来。
题意
题意就是给你 n n n个数,你有 p p p的概率选,求所有选出的数的异或平方和。
思路
像这种求异或的问题,我们可以将其转化为每一位进行求值,因为异或具有不进位的特点,所以每一位都可以独立,那么我们就可以把每个数字拆成 a i = ∑ x = 0 10 2 x b i , x a_i =\sum\limits_{x=0}^{10}2^xb_{i, x} ai=x=0∑102xbi,x,其中 b i , x b_{i, x} bi,x为 a i a_i ai的第 x x x位的数值(专业名词为二进制拆位)。那么两个数的异或平方和就可以写成 a i = ∑ x = 0 10 2 x a i , x , a j = ∑ y = 0 10 2 y a j , y a_i =\sum\limits_{x=0}^{1 0}2^xa_{i, x},a_j=\sum\limits_{y=0}^{10}2^ya_{j, y} ai=x=0∑102xai,x,aj=y=0∑102yaj,y
a
i
⊕
a
j
=
∑
k
=
0
10
2
k
[
a
i
,
k
≠
a
j
,
k
]
a_i ⊕ a_j=\sum\limits_{k=0}^{10} 2^k[a_{i, k} \not=a_{j, k}]
ai⊕aj=k=0∑102k[ai,k=aj,k]
(
a
i
⊕
a
j
)
2
(a_i ⊕a_j)^2
(ai⊕aj)2
=
(
∑
x
=
0
10
2
x
[
a
i
,
x
≠
a
j
,
x
]
)
(
∑
y
=
0
10
2
y
[
a
i
,
y
≠
a
j
,
y
]
)
=(\sum\limits_{x=0}^{10} 2^x[a_{i, x}\not=a_{j, x}])(\sum\limits_{y=0}^{10} 2^y[a_{i, y}\not=a_{j, y}])
=(x=0∑102x[ai,x=aj,x])(y=0∑102y[ai,y=aj,y])
那么对于多个数都可以进行如此操作,那么就变成求所有选出位数都是
1
1
1的期望数值是多少,我们定义一个
d
p
k
,
i
,
j
,
x
,
y
dp_{k,i,j,x,y}
dpk,i,j,x,y表示前面
k
k
k个数选择第
i
i
i位数值为
x
x
x,且第
j
j
j位数值为
y
y
y的期望为多少。
d
p
k
,
i
,
j
,
x
,
y
=
d
p
k
−
1
,
i
,
j
,
x
,
y
∗
(
1
−
p
k
)
+
d
p
k
−
1
,
i
,
j
,
x
⨁
b
i
,
k
,
y
⨁
b
j
,
k
∗
p
k
dp_{k,i,j,x,y} = dp_{k - 1, i, j, x, y} * (1 - p_k) + dp_{k - 1, i, j, x \bigoplus b_{i,k}, y \bigoplus b_{j,k}} * p_k
dpk,i,j,x,y=dpk−1,i,j,x,y∗(1−pk)+dpk−1,i,j,x⨁bi,k,y⨁bj,k∗pk,前面为不选的期望,后面为选的期望。
最后答案为
∑
i
=
0
10
∑
j
=
0
10
d
p
n
,
i
,
j
,
1
,
1
∗
2
i
+
j
\sum\limits_{i=0}^{10} \sum\limits_{j=0}^{10} dp_{n,i,j,1,1} * 2^{i+j}
i=0∑10j=0∑10dpn,i,j,1,1∗2i+j
肯能有人会问这样为什么就可以求出所有数的二进制值,因为我们选出来的数字的平方可以化成
(
∑
x
=
0
10
2
x
[
x
位为
1
]
)
(
∑
y
=
0
10
2
y
[
y
位为
1
]
)
(\sum\limits_{x=0}^{10} 2^x[x位为1])(\sum\limits_{y=0}^{10} 2^y[y位为1])
(x=0∑102x[x位为1])(y=0∑102y[y位为1]),所以会是答案肯定每一位有
1
1
1的位置互相相乘,所以可以推出,而期望是独立的只对选和不选会有影响,不选就继承,否则就异或上第
k
k
k个数相应位置上的数位值即可。
代码
#include <bits/stdc++.h>
#define x first
#define y second
#define min(a, b) ((a) < (b)?(a):(b))
#define max(a, b) ((a) > (b)?(a):(b))
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
typedef pair<LL, LL> PLL;
using PIII = pair<int, PII>;
const int N = 1010000, M = 510, MOD = 1e9 + 7;
const int inf = 2e9, xf3 = 0x3f3f3f3f;
const LL INF = 4e18, XF3 = 0x3f3f3f3f3f3f3f3f;
struct Node{
int l, r;
};
int n, m, k, a[N], s[N], b[N];
int e[N], ne[N], h[N], idx, w[N];
void add(int a, int b, int c){
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++;
}
LL f[20][20][2][2], fl[N], fr[N], p[N];
int L[N], R[N];
int gcd(int a, int b){
return b ? gcd(b, a % b) : a;
}
LL qmi(LL a, LL b, LL p){
LL res = 1;
while(b){
if(b & 1) res = res * a % p;
b >>= 1;
a = a * a % p;
}
return res;
}
LL inv(LL x){
return qmi(x, MOD - 2, MOD);
}
LL inv2[N], invp[N];
void solve(){
cin >> n;
for(int i = 1; i <= n; i ++) cin >> a[i];
for(int i = 0; i < 15; i ++){
for(int j = 0; j < 15; j ++){
for(int aa = 0; aa < 2; aa ++){
for(int bb = 0; bb < 2; bb ++){
f[i][j][aa][bb] = 0;
}
}
f[i][j][0][0] = 1;
}
}
for(int i = 1; i <= n; i ++){
cin >> p[i];
p[i] = p[i] * inv(10000) % MOD;
invp[i] = (1 - p[i] + MOD) % MOD;
}
/*
(a ^ b) * (a ^ b) = a的所有位数有的数与b的所有位数异或不为0的数的乘积
*/
for(int i = 1; i <= n; i ++){
for(int j = 0; j < 15; j ++){
for(int k = 0; k < 15; k ++){
int u1 = a[i] >> j & 1, u2 = a[i] >> k & 1;
int tmp[2][2] = {0};
for(int aa = 0; aa < 2; aa ++){
for(int bb = 0; bb < 2; bb ++){
tmp[aa][bb] = (f[j][k][aa][bb] * invp[i] % MOD + f[j][k][aa ^ u1][bb ^ u2] * p[i] % MOD) % MOD;
}
}
for(int aa = 0; aa < 2; aa ++){
for(int bb = 0; bb < 2; bb ++){
f[j][k][aa][bb] = tmp[aa][bb];
}
}
}
}
}
LL res = 0;
for(int i = 0; i < 15; i ++){
for(int j = 0; j < 15; j ++){
LL P2 = (1LL << i + j) % MOD;
res = (res + f[i][j][1][1] * P2 % MOD) % MOD;
}
}
cout << res << "\n";
return;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
//cout<<fixed<<setprecision(0)<<"\n";
int _ = 1;
cin>>_;
while(_ --){
solve();
}
return 0;
}
/*
*/