题意
三维空间中任选两点,将两点间的开关按下。进行k次选点,问最终闭合开关的个数的期望。
思路
令f[i]表示选i次点后,该点被按了奇数次的期望,g[i]表示选i次点后,该点被按了偶数次的期望。最终结果就是
∑
x
,
y
,
z
f
[
k
]
\sum_{{x,y,z}}{f[k]}
x,y,z∑f[k]
f[i]和g[i]的递推式如下:
{
f
[
i
]
=
p
∗
g
[
i
−
1
]
+
(
i
−
p
)
∗
f
[
i
−
1
]
g
[
i
]
=
p
∗
f
[
i
−
1
]
+
(
1
−
p
)
∗
g
[
i
−
1
]
f
[
i
]
+
g
[
i
]
=
1
\left\{\begin{aligned} &f[i] = p*g[i-1]+(i-p)*f[i-1] \\ &g[i] = p*f[i-1]+(1-p)*g[i-1]\\ &f[i]+g[i]=1 \end{aligned} \right.
⎩⎪⎨⎪⎧f[i]=p∗g[i−1]+(i−p)∗f[i−1]g[i]=p∗f[i−1]+(1−p)∗g[i−1]f[i]+g[i]=1
联立后可以解得
f
[
i
]
=
p
+
(
1
−
2
p
)
∗
f
[
i
−
1
]
f[i] = p+(1-2p)*f[i-1]
f[i]=p+(1−2p)∗f[i−1]
f
[
1
]
=
p
f[1]=p
f[1]=p
令
A
=
1
−
2
p
A=1-2p
A=1−2p
可以推出
f
[
i
]
=
p
+
A
∗
f
[
i
−
1
]
=
p
+
A
p
+
A
2
∗
f
[
i
−
2
]
=
p
+
A
p
+
A
2
p
+
A
3
f
[
i
−
3
]
=
p
∗
(
1
+
A
+
A
2
+
.
.
.
+
A
i
−
2
)
+
A
i
−
1
f
[
1
]
=
p
∗
1
−
A
i
−
1
1
−
A
+
A
i
−
1
∗
p
.
\begin{aligned} f[i]&=p+A*f[i-1]\\ &=p+Ap+A^2*f[i-2]\\ &=p+Ap+A^2p+A^3f[i-3]\\ &=p*(1+A+A^2+...+A^{i-2})+A^{i-1}f[1]\\ &=p*\frac{1-A^{i-1}}{1-A}+A^{i-1}*p \end{aligned}.
f[i]=p+A∗f[i−1]=p+Ap+A2∗f[i−2]=p+Ap+A2p+A3f[i−3]=p∗(1+A+A2+...+Ai−2)+Ai−1f[1]=p∗1−A1−Ai−1+Ai−1∗p.
将A回代后可得
f
[
i
]
=
1
2
−
1
2
∗
(
1
−
2
p
)
i
f[i]=\frac{1}{2}-\frac{1}{2}*(1-2p)^i
f[i]=21−21∗(1−2p)i
f[k]即为答案。
p的求法:
p
=
p
x
∗
p
y
∗
p
z
p=p_x*p_y*p_z
p=px∗py∗pz
对于每一维:
p
=
1
−
(
i
−
1
)
∗
(
i
−
1
)
+
(
m
−
i
)
∗
(
m
−
i
)
m
∗
m
p=1-\frac{(i-1)*(i-1)+(m-i)*(m-i)}{m*m}
p=1−m∗m(i−1)∗(i−1)+(m−i)∗(m−i)
刚开始做的时候,我是对每一维求出该维的概率期望,在将所有维的期望乘起来。即利用
E
(
X
Y
Z
)
=
E
(
X
)
E
(
Y
)
E
(
Z
)
E(XYZ)=E(X)E(Y)E(Z)
E(XYZ)=E(X)E(Y)E(Z)
但本题这样求解并不适用。因为期望方程
f
[
i
]
=
1
2
−
1
2
∗
(
1
−
2
p
)
i
f[i]=\frac{1}{2}-\frac{1}{2}*(1-2p)^i
f[i]=21−21∗(1−2p)i并不满足上式。所以应该用三个for循环去枚举每一个点,求每个点的概率期望。
代码:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ld double
#define ull unsigned long long
#define __ ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
const int maxn = 5e5 + 10;
const int maxm = 5e5 + 10;
const ll mod = 1e9 + 7;
const double eps = 1e-10;
int x, y, z, k;
inline ld P(int i, int m) {
return (ld) (1.0 - ((m - i) * (m - i) + (i - 1.0) * (i - 1.0)) / (m * m));
}
ld pow_mod(ld a, int b) {
ld ans = 1.0;
while (b) {
if (b & 1)ans = ans * a;
a = a * a;
b >>= 1;
}
return ans;
}
int main() {
__;
int _;
cin >> _;
for (int sce = 1; sce <= _; ++sce) {
cin >> x >> y >> z >> k;
cout << "Case " << sce << ": ";
if (k == 0)cout << 0 << endl;
else {
ld ans = 0.0;
for (int i = 1; i <= x; ++i) {
for (int j = 1; j <= y; ++j) {
for (int t = 1; t <= z; ++t) {
ld p = P(i, x) * P(j, y) * P(t, z);
ans += 0.5 - 0.5 * pow_mod(1.0 - 2.0 * p, k);
}
}
}
cout << fixed << setprecision(10) << ans << endl;
}
}
return 0;
}