题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2652
题目大意:给一个N*M*P的立方体,其中包含N*M*P个体积为1的立方体,每个小立方体中有一盏灯,初始状态每盏灯都是灭的,现在有K次操作,每次操作随机选择两个点的坐标,然后按一下以这两个点为对角线的小立方体内的开关,即开变关,关变开。问K次操作之后期望的亮灯数。
解题思路:
把每个灯经过K次操作亮着的概率P求出来,因为每个灯是独立的,最后的期望也就是ΣPi*1+(1-Pi)*0。
对于一个灯来说, 设f[i]是经过i次操作亮着的概率,g[i]是经过i次操作不亮的概率,则有f[i]+p[i]=1,f[i]=f[i-1]*(1-p)+g[i-1]*p,这里的p是操作一次能操作到这个灯的概率。
通过这两个式子,能得到f[i]=f[i-1]*(1-2p)+p,两边加上b/(a-1),也就是0.5,成为等比数列,最后得到f[i]=0.5-0.5*(1-2p)^i。//不太懂,木推出来。。。
那么只要对每个灯求出p就能算出答案了。能操作到这个灯等价于选的两个点的坐标在x轴,y轴,z轴都分别在这个灯坐标的两侧,对每个轴分别算符合的情况,然后相乘,最后除以所有情况就是概率。
代码如下:
#include<stdio.h>
#include<cmath>
using namespace std;
double p(int x,int n)
{
double a;
return a=((n-x+1)*x*2-1)*1.0/(n*n*1.0);
}
inline double handle (double p,int k) {
return (1 - pow(1 - 2 * p, k)) / 2;
}
int main()
{
int T,n,m,q,cnt,cas=1;
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d%d",&n,&m,&q,&cnt);
double ret=0;
for(int i=1; i<=n; i++)
{
double px=p(i,n);
for(int j=1; j<=m; j++)
{
double py=p(j,m);
for(int k=1; k<=q; k++)
{
double pz=p(k,q);
ret+=handle(px*py*pz,cnt);
}
}
}
printf("Case %d: %.10lf\n",cas++,ret);
}
return 0;
}