您的位置:首页 > 其它

HDU 5245

2015-06-03 21:44 295 查看
题目大意:

每次随机选择两个点,便把这两个点之间形成的子矩阵上的每一个方块涂色,问随机选择k次,整个m*n的矩阵中有多少个小方块被涂上了颜色

这道题不难,但自己智商实在捉急,一直想不出来。。。

因为这里n,m<=500,所以总共250000个方块,我们可以考虑的是每一个方块在随机选择1次后被染色的概率 p[i][j]

那么k次后就变成了 1-(1-p[i][j])^k的概率了,我们将所有概率相加就得到了总共的染色块数

至于怎么计算被染色概率就是可以将整个矩形块分解,然后去计算所有不能包括当前点的所有点对组合,求出不被染色的次数

总的次数n*m*n*m 会超int

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
#define N 505
#define ll long long
double p

;
int n , m , k;
//计算i,j位置的正方形小块不包含的取点总数
ll cal(int i , int j)
{
ll c1 = i-1 , c2=(i-1)*(m-j) , c3=m-j , c4=(n-i)*(m-j);
ll c5 = n-i , c6=(n-i)*(j-1) , c7=j-1 , c8=(i-1)*(j-1);
ll ret = 0;
ret+=c1*(c1+c2+c8)+c2*(c2+c1+c8+c3+c4)+c3*(c2+c3+c4)+c4*(c2+c3+c4+c5+c6)+c5*(c4+c5+c6)+c6*(c4+c5+c6+c7+c8)+c7*(c6+c7+c8)+c8*(c6+c7+c8+c1+c2);
//  if(ret<0 || ret>n*m*n*m) cout<<i<<" "<<j<<" "<<ret<<endl;
return ret;
}

double q_pow(double a , int b)
{
double ret=1;
while(b){
if(b&1) ret*=a;
a*=a;
b>>=1;
}
return ret;
}

int main()
{
#ifndef ONLINE_JUDGE
freopen("a.in" , "r" , stdin);
#endif
int T , cas=0;
scanf("%d" , &T);
while(T--)
{
scanf("%d%d%d" , &n , &m , &k);
double ret = 0;
ll all = (ll)n*m*n*m;
// cout<<all<<endl;
for(int i=1 ; i<=n ; i++)
for(int j=1 ; j<=m ; j++){
p[i][j] = cal(i,j)*1.0/all;
// if(p[i][j]>=1||p[i][j]<0) cout<<i<<" "<<j<<" "<<p[i][j]<<endl;
p[i][j] = q_pow(p[i][j] , k);
ret += 1-p[i][j];
}
printf("Case #%d: %.0f\n" , ++cas , ret);

}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: