HDU 5245 - Joyful

一道比较明显的公式题

给的参数很少,数值也不大(≤500/≤20)

题意大致是:进行K次染色,每次染色会随机选取一个以(x1,y1),(x2,y2)为一组对角的子矩阵进行染色,求K次染色后染色面积的期望值(四舍五入)。

[html]  view plain  copy
  1. 样例1:(n,m,k)=(3,3,1)   
  2. Case #1: 4  
  3. (这组样例中,每一种可能染色方案的面积总和为289,染色的方案数共有n*n*m*m=3^4=81种,因此期望为3.56790123,四舍五入后答案为4)  


显而易见的是,当K=1时,期望被染色的面积会等于每个1*1的方块被染色的期望累加之和。


假设K=1时即只染色一次时,位于第x行第y列的方块被染色的概率为A[x,y]

在K次操作后被染色的期望假设为P[x,y],可以用

[html]  view plain  copy
  1. P[x,y]=1-(1-A[x,y])^k  
来计算。


此时我们的问题转向了如何计算A[x.y]上

由题目描述,一次染色中可能的操作有n^2*m^2种

计算A[x,y]时,我们可以把整个矩阵做如下拆分


当前计算的方块为[x,y],即图中编号为5的部分

将其他部分拆分成图上8个区域,则可得到以下关系

[html]  view plain  copy
  1. 对于一种染色方案能够覆盖方块[x,y]时  
  2. ①[x1,y1]取在区域1内时,[x2,y2]可以在5、6、8、9四个区域内任取;  
  3. ②[x1,y1]取在区域2内时,[x2,y2]可以在4、5、6、7、8、9六个区域内任取;  
  4. ③[x1,y1]取在区域3内时,[x2,y2]可以在4、5、7、8四个区域内任取;  
  5. ④[x1,y1]取在区域4内时,[x2,y2]可以在2、3、5、6、8、9六个区域内任取;  
  6. ⑤[x1,y1]取在区域5内时,[x2,y2]可以在所有区域内任取;  
  7. ⑥[x1,y1]取在区域6内时,[x2,y2]可以在1、2、4、5、7、8六个区域内任取;  
  8. ⑦[x1,y1]取在区域7内时,[x2,y2]可以在2、3、5、6四个区域内任取;  
  9. ⑧[x1,y1]取在区域8内时,[x2,y2]可以在1、2、3、4、5、6六个区域内任取;  
  10. ⑨[x1,y1]取在区域1内时,[x2,y2]可以在1、2、4、5四个区域内任取;  
按照这个关系,即可推出A[x,y]的表达式。


P.S.:本题因为计算过程中会出现n^2*m^2大小的计算,因此需要注意int溢出的问题

[cpp]  view plain  copy
  1. #include<iostream>  
  2. #include<cstdio>  
  3. #include<cmath>  
  4. using namespace std;  
  5.   
  6. int main()  
  7. {  
  8.     int t,tm,k;  
  9.     double n,m;  
  10.     scanf("%d",&t);tm=t;  
  11.     while(t--)  
  12.     {  
  13.         scanf("%lf%lf%d",&n,&m,&k);  
  14.         double ans=0;  
  15.         for(double i=1;i<=n;i++)  
  16.             for(double j=1;j<=m;j++)  
  17.             {  
  18.                 double p=m*n;  
  19.                 p+=(i-1)*(j-1)*(n-i+1)*(m-j+1);  
  20.                 p+=(i-1)*(m-j)*(n-i+1)*j;  
  21.                 p+=(j-1)*(n-i)*(m-j+1)*i;  
  22.                 p+=(n-i)*(m-j)*i*j;  
  23.                 p+=(i-1)*m*(n-i+1);  
  24.                 p+=(m-j)*n*j;  
  25.                 p+=(n-i)*m*i;  
  26.                 p+=(j-1)*n*(m-j+1);  
  27.                 p=p/n/n/m/m;  
  28.                 ans+=1-(pow(1-p,k));  
  29.             }  
  30.             printf("Case #%d: %d\n",tm-t,int(ans+0.5));  
  31.     }  
  32.     return 0;  
  33. }  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值