You are given a 3D grid, which has dimensions X, Y 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;
}