题意:一个X * Y * Z的立方体,每个灯泡一开始都是关闭的,有m次反转操作,每次操作随机选择两个点,将两个点之间的灯泡全部反转,求灯泡亮的期望个数。
题解:期望
考虑每个灯泡的贡献,每个灯泡亮着的概率就是单个灯泡的期望,全部累加就是结果。
对于点C(x,y,z)只有当被选中的2个点A(x1,y1,z1),B(x2,y2,z2),满足x1<=x<=x2且y1<=y<=y2且z1<=z<=z2时,该点的状态才会改变,我们现求单个被选择(改变)的概率p。
先考虑一维,组合表示排列:p = ACB = 1 - ABC - CAB
三维就是三个概率相乘。
接下来考虑已经进行x次选择。
f
(
x
)
f(x)
f(x)表示被选择奇数次概率,即最后灯亮,
g
(
x
)
g(x)
g(x)表示偶数次概率,即最后灯灭。
f
(
x
)
+
g
(
x
)
=
1
f(x)+g(x) = 1
f(x)+g(x)=1 ①
f
(
x
)
=
f
(
x
−
1
)
∗
(
1
−
p
)
+
g
(
x
−
1
)
∗
p
f(x) = f(x - 1) * (1 - p) + g(x - 1) * p
f(x)=f(x−1)∗(1−p)+g(x−1)∗p ②
两式联立化简可以得到
f
(
x
)
−
1
/
2
=
(
1
−
2
∗
p
)
(
f
(
x
−
1
)
−
1
/
2
)
f(x)-1/2=(1-2*p)(f(x-1)-1/2)
f(x)−1/2=(1−2∗p)(f(x−1)−1/2),
f
(
1
)
=
p
f(1) = p
f(1)=p,等比公式可以化简得到
f
(
m
)
=
(
1
−
(
1
−
2
∗
p
)
m
)
/
2
f(m)=(1-(1-2*p) ^ m)/2
f(m)=(1−(1−2∗p)m)/2,然后每个点累加即可。
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<fstream>
#include<set>
#include<map>
#include<sstream>
#include<iomanip>
#define ll long long
using namespace std;
int t, x, y, z, m;
double cal(int x, int n) {
return 1 - 1.0 * (x - 1) * (x - 1) / n / n - 1.0 * (n - x) * (n - x) / n / n;
}
int main() {
scanf("%d", &t);
int cas = 0;
while (t--) {
scanf("%d%d%d%d", &x, &y, &z, &m);
double ans = 0;
for (int i = 1; i <= x; i++) {
for (int j = 1; j <= y; j++) {
for (int k = 1; k <= z; k++) {
double p = cal(i, x) * cal(j, y) * cal(k, z);
ans += 1.0 * (1 - pow(1 - 2 * p, m)) / 2;
}
}
}
printf("Case %d: %f\n", ++cas, ans);
}
return 0;
}