题面:

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,

....

题意:

一个大立方体里面选择k次小的立方体,将小的立方体里面灯泡的开关按一下,问最后的小灯泡亮起的个数期望

思路:

单独计算每个点的贡献

设\(f(x)\)是一共按了x次开关,某一个小灯泡被按了奇数次的概率,\(p\)是某一次被按下的概率

其中 \(f(1) = p\)

所以,有以下公式

\[f(k)=(1-p)f(k-1)+p(1-f(k-1))
\]

化简得:

\[f(k)=(1-p)f(k-1)+p-p*f(k-1)
\]

\[f(k)=(1-2p)f(k-1)+p
\]

同理:

\[f(k-1)=(1-2p)f(k-2)+p
\]

代入\(f(k)\):

\[f(k) = (1-2p)[(1-2p)f(k-2)+p]+p
\]

\[f(k) = (1-2p)^2f(k-2)+p+p(1-p)
\]

写出\(f(k-2)\),并代入上式,可得:

\[f(k) = (1-2p)^3f(k-3)+p+p(1-p)+p(1-2p)^2
\]

...

递推可得:

\[f(k) = (1-2p)^{k-1}f(1) + p(1-2p)^{k-2}+p(1-2p)^{k-3}+...+p
\]

通过等比数列求和:

\[f(x)=(1-2p)^{k-1}*p+[1-(1-2*p)^{k-1}]/2
\]

化简得:

\[f(x) = [1-(1-2*p)^{k}]/2
\]

其中,\(p\)的计算方法为,分别计算\(x,y,z\)被选中的概率,再相乘

#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#define fuck(x) cout<<#x<<" = "<<x<<endl;
#define debug(a,i) cout<<#a<<"["<<i<<"] = "<<a[i]<<endl;
#define ls (t<<1)
#define rs ((t<<1)+1)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 100086;
const int maxm = 100086;
const int inf = 2.1e9;
const ll Inf = 999999999999999999;
const int mod = 1000000007;
const double eps = 1e-6;
const double pi = acos(-1); double q_pow(double a,int b){
double ans=1;
while(b){
if(b&1){
ans*=a;
}
a*=a;
b>>=1;
}
return ans;
} double f(double p,int k){
if(k==0){return 0;}
double tmp = q_pow(1.0-2*p,k);
return (1.0-tmp)/2;
}
double f1(double p,int k){
if(k==0){return 0;}
if(k==1){return p;}
return (1.0-2*p)*f1(p,k-1)+p;
} int main()
{
// ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif // ONLINE_JUDGE int T;
scanf("%d",&T);
int cas = 0;
while(T--){
int x,y,z,K;
scanf("%d%d%d%d",&x,&y,&z,&K);
int sum = x*y*z;
double ans = 0;
for(int i=1;i<=x;i++){
for(int j=1;j<=y;j++){
for(int k=1;k<=z;k++){
double p1 = 1.0-1.0*((i-1)*(i-1)+(x-i)*(x-i))/(x*x);
double p2 = 1.0-1.0*((j-1)*(j-1)+(y-j)*(y-j))/(y*y);
double p3 = 1.0-1.0*((k-1)*(k-1)+(z-k)*(z-k))/(z*z);
double pp = p1*p2*p3;
ans+=f(pp,K);
}
}
}
printf("Case %d: %f\n",++cas,ans);
} return 0;
}
05-11 19:39