bzoj 2969: 矩形粉刷 概率期望

题目:

为了庆祝新的一年到来,小M决定要粉刷一个大木板。大木板实际上是一个W*H的方阵。小M得到了一个神奇的工具,这个工具只需要指定方阵中两个格子,就可以把这两格子为对角的,平行于木板边界的一个子矩形全部刷好。小M乐坏了,于是开始胡乱地使用这个工具。
假设小M每次选的两个格子都是完全随机的(方阵中每个格子被选中的概率是相等的),而且小M使用了K次工具,求木板上被小M粉刷过的格子个数的期望值是多少。

题解:

我们发现我们无法直接进行概率期望dp
因为状态无法记录.
而在这道题中被染色的格子的位置不同也决定着不同的状态.

所以我们考虑转化问题,我们可以分别计算出每个格子k次后被染成黑色的概率.
然后我们求概率之和即为期望.
所以我们把问题转化成了求概率。
因为我们要求的是一个格子k次操作后被染成黑色的概率,而每次操作是染色一个子矩阵.
直接不好计算,所以考虑补集转化.
我们统计每个点在k次操作后仍然没有被染成黑色的概率。然后用1减即可。
至于怎么计算k次操作后没有被染成黑色的概率,我们算出一次染色没有被染到的概率.
再求k次方既可.

一次染色没有被染到的概率瞎XX搞一下就好了.

#include <cstdio>
#include <cstring>
#include <algorithm>
    using namespace std;
typedef long long ll;
inline void read(int &x){
    x=0;char ch;bool flag = false;
    while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
    while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
int n,m;
#define sqr(x) ((x)*(x))
inline double calc(int i,int j){
    double upside = .0;
    upside += sqr(1.0*n*(j-1)) + sqr(1.0*(i-1)*m);
    upside += sqr(1.0*(n-i)*m) + sqr(1.0*n*(m-j));
    upside -= sqr(1.0*(i-1)*(j-1)) + sqr(1.0*(n-i)*(m-j));
    upside -= sqr(1.0*(i-1)*(m-j)) + sqr(1.0*(n-i)*(j-1));
    double dnside = sqr(1.0*n*m);
    return upside/dnside;
}
inline double qpow(double x,int p){
    double ret = 1.0;
    for(;p;p>>=1,x=x*x) if(p&1) ret=ret*x;
    return ret;
}
int main(){
    int T;T = 1;
    while(T--){
	int k;read(k);read(n);read(m);
	double ans = .0;
	for(int i=1;i<=n;++i){
	    for(int j=1;j<=m;++j){
		ans += 1.0 - qpow(calc(i,j),k);
	    }
	}
	printf("%.0f\n",ans);
    }
    return 0;
}
posted @ 2017-03-28 21:00  Sky_miner  阅读(227)  评论(0编辑  收藏  举报