UVA11605 Lights inside a 3d Grid(概率公式)

题意:已知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],则由全期望公式可得结论:灯泡亮数的期望为 1p[i]=p[i]
结论:共n件事情,每件事情发生的概率为pi,则事件发生的件数期望为 p[i]
2.如何得到每个灯泡k次后亮的概率。可以先考虑灯泡每次状态改变的概率。通过推导可以得到如下结论。
结论1:每次在[1,n]区间内选择两点,x包含在两点区间内的概率为 (2x(n+1x)1)/(nn)
结论2:每次在n*m的平面内随机选择两个格点,(x,y)包含在所选两格点围城矩形内的概率为 (2x(n+1x)1)(2y(m+1y)1)/(nmnm)
空间内的概率类似可得。
3.将第i个灯泡每次状态改变的概率记作p[i],那么k次后灯泡亮的概率为

j,j<=kC(k,j)Power(p[i],j)Power(1p[i],kj)

结论:由组合数学知识可以推导得,上述式子 =(1Power(12pi,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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值