题意:已知n*m*p的立方体的每个格点有一个灯泡,初始灯泡都熄灭。每次随机选一个格点A(x1,y1,z1),再随机选一个格点B(x2,y2,z2),将满足
min(x1,x2)=<x<=max(x1,x2)
,y,z坐标类似条件的个点内灯泡状态全部改变,求k次随机选择后灯泡亮数的期望。
解法:
1.考虑每个灯泡在k次随机选择后的亮灭情况。假设已知第i个灯泡k次后亮的概率是p[i],则由全期望公式可得结论:灯泡亮数的期望为
∑1∗p[i]=∑p[i]
结论:共n件事情,每件事情发生的概率为pi,则事件发生的件数期望为
∑p[i]
2.如何得到每个灯泡k次后亮的概率。可以先考虑灯泡每次状态改变的概率。通过推导可以得到如下结论。
结论1:每次在[1,n]区间内选择两点,x包含在两点区间内的概率为
(2∗x∗(n+1−x)−1)/(n∗n)
结论2:每次在n*m的平面内随机选择两个格点,(x,y)包含在所选两格点围城矩形内的概率为
(2∗x∗(n+1−x)−1)∗(2∗y∗(m+1−y)−1)/(n∗m∗n∗m)
空间内的概率类似可得。
3.将第i个灯泡每次状态改变的概率记作p[i],那么k次后灯泡亮的概率为
∑j为奇数,j<=kC(k,j)∗Power(p[i],j)∗Power(1−p[i],k−j)
结论:由组合数学知识可以推导得,上述式子 =(1−Power(1−2∗pi,k))/2
得到第i个灯泡k次后亮的概率后,代入1的全期望公式即可得到答案
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<iostream>
#include<vector>
#include<map>
#include<set>
#define ll long long
using namespace std;
const ll maxn = 100+10;
int t;
ll n,m,p,k;;
double po[maxn][maxn][maxn];
double po2[maxn][maxn][maxn];
double ans;
ll cas;
double Power(double a,ll b){
double tmp=1.0;
while(b){
if(b&1) { tmp=tmp*a; b--; }
b>>=1; a=a*a;
}
return tmp;
}
int main(){
scanf("%d",&t);
cas=0;
while(t--){
scanf("%lld%lld%lld%lld",&n,&m,&p,&k);
ans=0.0;
for(ll x=1;x<=n;x++){
for(ll y=1;y<=m;y++){
for(ll z=1;z<=p;z++){
po[x][y][z]=(double)(2.0*x*(n+1-x)-1.0)*(double)(2.0*y*(m+1-y)-1.0)*(double)(2.0*z*(p+1-z)-1.0)/(double)((n*m*p)*(n*m*p));
po2[x][y][z]=(double)(1.0-Power(1.0-2.0*po[x][y][z],k))/2.0;
ans+=po2[x][y][z];
}
}
}
printf("Case %lld: %.10lf\n",++cas,ans);
}
return 0;
}