Lights inside 3D Grid LightOJ - 1284 (期望+取反问题)

You are given a 3D grid, which has dimensions XY and Z. Each of the X x Y x Z cells contains a light. Initially all lights are off. You will have K turns. In each of the K turns,

1.      You select a cell A randomly from the grid,

2.      You select a cell B randomly from the grid and

3.      Toggle the states of all the bulbs bounded by cell A and cell B, i.e. make all the ON lights OFF and make all the OFF lights ON which are bounded by A and B. To be clear, consider cell A is (x1, y1, z1) and cell B is (x2, y2, z2). Then you have to toggle all the bulbs in grid cell (x, y, z) where min(x1, x2) ≤ x ≤ max(x1, x2)min(y1, y2) ≤ y ≤ max(y1, y2) and min(z1, z2) ≤ z ≤ max(z1, z2).

Your task is to find the expected number of lights to be ON after K turns.

Input

Input starts with an integer T (≤ 50), denoting the number of test cases.

Each case starts with a line containing four integers X, Y, Z (1 ≤ X, Y, Z ≤ 100) and K (0 ≤ K ≤ 10000).

Output

For each case, print the case number and the expected number of lights that are ON after Kturns. Errors less than 10-6 will be ignored.

Sample Input

5

1 2 3 5

1 1 1 1

1 2 3 0

2 3 4 1

2 3 4 2

Sample Output

Case 1: 2.9998713992

Case 2: 1

Case 3: 0

Case 4: 6.375

Case 5: 9.09765625

思路:计算每个点亮的期望然后相加就是总的期望(因为点是离散的,按离散型概率来计算)。

计算灯是否亮,就是看取反操作的次数是否为奇数。

其实这题的概率其实包括两部分,第一部分是被选中的概率,另一部分是被选奇数次的概率。

计算每个点被选中的概率,只需要计算x,y.z三个坐标都被包括的概率之积就行。(计算的时候可以采用容斥的思想先计算不包括的概率)。

计算被包括奇数次的,就是最后还亮着的。

设f(x)为选择x次区间时,状态改变次数为奇数的概率,g(x)为状态改变次数为偶数的概率。
f(x)=(1-p)*f(x-1)+p*g(x-1)
g(x)=(1-p)*g(x-1)+p*f(x-1)
f(x)+g(x)=1

下图来自一位大佬的博客。

可以推导出f[x]-1/2为一个等比数列

代码:

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
#include <map>
#include <vector>
#include <set>
#include <string>
#include <math.h>
#include <stack>
using namespace std;
typedef long long ll;
const int maxn = 1e5+10;
#define inf 0x3f3f3f3f
double getP(int i,int x)
{
    return 1.0-1.0*((i-1)*(i-1)+(x-i)*(x-i))/(x*x);
}
int main(int argc, char const *argv[])
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
        freopen("out.txt","w",stdout);
    #endif
    int T;
    int Case=0;
    cin>>T;
    while(T--)
    {
        int x,y,z,d;
        scanf("%d%d%d%d",&x,&y,&z,&d);
        double ans=0.0;
        for(int i=1;i<=x;i++)
        {
            for(int j=1;j<=y;j++)
            {
                for(int k=1;k<=z;k++)
                {
                    double tmp=0.f;
                    tmp=getP(i,x);
                    tmp*=getP(j,y);
                    tmp*=getP(k,z);
                    ans+=0.5-0.5*pow(1-2*tmp,1.0*d);
                }   
            }
        }
        printf("Case %d: %.6lf\n",++Case,ans);
    }
    return 0;
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值