Lights inside 3D Grid LightOJ - 1284
给一个三维格子,每个维度的大小为 X,Y,Z,每个位置有一盏灯,刚开始的时候每个灯都关着,进行 K 次操作:
(1)随机选一个格子 A
(2)随机再选一个格子 B
(3)改变由 A,B 包围起来的方体的灯的状态(开→关,关→开)
计算 K 次操作后,开灯数的期望。
对于每一个点 (x,y,z),设选中的格点分别为 (x1,y1,z1),(x2,y2,z2),只有当 x1≤x≤x2 且 y1≤y≤y2 且 z1≤z≤z2 时,点的状态才会改变,设点分别在这三个区间内的概率为 px,py,pz,则 px=1− 不在[x1,x2] 区间内的概率,而不在 [x1,x2] 区间内的概率 = 随机的两个边界点都在 x 的同一侧的概率,因此有:
px=1−(Xx−1)2−(XX−x)2
其中 X 是 x 所在维度的大小。
设 p 为 (x,y,z) 在 A,B 之间的概率,则
p=pxpypz
总共要进行 K 轮,那么每一轮使得 (x,y,z) 在 A,B 之间的概率都是 p,当该点总共在区间内的次数是奇数次时,这个灯才是亮着的状态,设 f(i) 为 i 轮之后,在区间内的次数是奇数次的概率,g(i) 为相应偶数次的概率,则:
f(i)g(i)f(i)+g(i)=pg(i−1)+(1−p)f(i−1)=pf(i−1)+(1−p)g(i−1)=1
解上述等式组,得:
f(i)f(i)f(i)+af(i)af(i)−21f(i)−21f(i)=p(1−f(i−1))+(1−p)f(i−1)=p+(1−2p)f(i−1)=(1−2p)(f(i−1)+a)=−2pa+(1−2p)f(i−1)=−21=(1−2p)(f(i−1)−21)=(1−2p)i−1(f(1)−21)=−2(1−2p)i=21−(1−2p)i
因此 f(K)=21−(1−2p)K。
代码如下:
#include<iostream>
#include<cstdio>
#define P(x,X) (1-(1.0*(x-1)*(x-1)+(X-x)*(X-x))/(X*X))
using namespace std;
int T,iCase,X,Y,Z,K;
double res,p;
double pow(double x,int p){
double base=x,res=1;
while(p){
if(p&1)res*=base;
base*=base;
p>>=1;
}
return res;
}
int main(){
#ifdef WINE
freopen("data.in","r",stdin);
#endif
scanf("%d",&T);
while(T--){
scanf("%d%d%d%d",&X,&Y,&Z,&K);
res=0;
for(int x=1;x<=X;x++)
for(int y=1;y<=Y;y++)
for(int z=1;z<=Z;z++){
p=P(x,X)*P(y,Y)*P(z,Z);
res+=(1-pow(1-2*p,K))/2;
}
printf("Case %d: %.8lf\n",++iCase,res);
}
return 0;
}
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200326081006442.png)