bzoj2969 矩形粉刷

学习一波用markdown写题解的姿势QAQ

题意

给你一个w*h的矩形网格,每次随机选择两个点,将以这两个点为顶点的矩形内部的所有小正方形染黑,问染了k次之后期望有多少个黑色格子.

分析

一开始看错题以为是求染黑所有格子的期望步数差点吓傻了...然后发现求的是染黑格子的期望个数,那么就可以无脑上期望的线性性了.

\(\text{某个格子对期望的贡献}\)

\(=\text{这个格子最后被染黑的概率}\)

\(=1-这个格子最后没被染黑的概率\)

\(=1-(染色一次时这个格子这个格子没有被染黑的概率)^k\)

那么单次染色无法染黑某个格子的概率只需要数一数总的选择方案数和包含这个格子的选择方案数即可.
注意包含这个格子的矩形和包含这个格子的选择方案不是一一对应的.
某个长宽均大于等于2的矩形对应4种选择的的方案
(可以选择左上-右下 或 左下-右上,每种选择方式又对应两种方案,因为选择的两个顶点是有顺序的,下面两种类似)
长宽有一个为1的矩形对应2种选择的方案
长宽均为1的矩形对应1种选择的方案

注意到关于矩形的中心点对称的位置算出来的结果是一样的,可以利用这个将复杂度降低到1/4,然而我还是比bz上的榜一慢三倍...榜一太神啦

    #include<cstdio>
    typedef long long ll;
    typedef  double ld;
    ld qpow(ld a,int x){
      ld ans=1;
      for(;x;x>>=1,a=a*a){
        if(x&1)ans=ans*a;
      }
      return ans;
    }
    int k,w,h;ll tot;
    ld p(int x,int y){
      long long sum=0;
      int x1=x,x2=w-x+1,y1=y,y2=h-y+1;
      sum=x1*1ll*y1*y2*x2*4-x1*x2*2-y1*y2*2+1;
      //printf("%d %d %lld %lld\n",x,y,sum,tot);
      return (tot-sum)/(ld)(tot);
    }
    int main(){
      scanf("%d%d%d",&k,&w,&h);
      ld ans=w*h;tot=w*1ll*w*1ll*h*1ll*h;
      //printf("%.4f\n",(double)p(1,1));
      int ww=w/2,hh=h/2;
      for(int i=1;i<=ww;++i){
        for(int j=1;j<=hh;++j){//printf("a%d %d\n",i,j);
          ans-=qpow(p(i,j),k)*4;
        }
      }
      if(h&1){
        for(int i=1;i<=ww;++i){//printf("b%d %d\n",i,h/2+1);
          ans-=qpow(p(i,h/2+1),k)*2;
        }
      }
      if(w&1){
        for(int j=1;j<=hh;++j){//printf("c%d %d\n",w/2+1,j);
          ans-=qpow(p(w/2+1,j),k)*2;
        }
      }
      if((h&1)&&(w&1)){//printf("d%d %d\n",w/2+1,h/2+1);
        ans-=qpow(p(w/2+1,h/2+1),k);
      }
      printf("%.0f\n",(double)ans);
      return 0;
    }

转载于:https://www.cnblogs.com/liu-runda/p/6627759.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值