zoukankan      html  css  js  c++  java
  • 【CF708E】Student's Camp(动态规划)

    点此看题面

    • 初始有一张((n+2) imes m)的网格图。
    • 共操作(k)轮,每轮除第一行和最后一行外每行的第一个格子和最后一个格子均有(p=frac ab)的概率被删除。
    • 求最终图连通的概率。
    • (n,mle1500,kle10^5)

    暴力动态规划

    首先(k)相对(n,m)要大许多,肯定不会把它放到(DP)状态中。

    因此我们只需要考虑最终状态,那就只需要设(q_i)表示在(k)轮删除操作中恰好进行(i)次的概率:

    [q_i=C_k^ip^i(1-p)^{k-i} ]

    由于前后的删除相对独立,因此设(w_{l,r})表示最后被删得恰好只剩([l,r])的概率,就有:

    [w_{l,r}=p_{l-1} imes p_{m-r} ]

    这样一来,如果我们设(f_{i,l,r})表示第(i)行最终被删得只剩([l,r])且前(i)行连通的概率,就只需考虑这一行与上一行是否连通:

    [f_{i,l,r}=w_{l,r} imessum_{[l,r]cap[l',r'] ot=emptyset}f_{i-1,l',r'} ]

    两个区间有交,可以容斥用总方案数减去无交的方案数:

    [f_{i,l,r}=w_{l,r} imes(sum_{l'le r'}f_{i-1,l',r'}-sum_{l'le r'<l}f_{i-1,l',r'}-sum_{r<l'le r'}f_{i-1,l',r'}) ]

    但这样的复杂度显然不太对劲,需要优化。

    前缀和优化

    首先我们发现(f_{i,l,r})这状态数已经达到了三维,显然从这里就需要开始改造。

    因此给它做两次前缀和:

    [g_{i,r}=sum_{l=1}^rf_{i,l,r}\ s_{i,j}=sum_{r=1}^jg_{i,r} ]

    那么先前的转移式就可以写作:

    [f_{i,l,r}=w_{l,r} imes(s_{i-1,m}-s_{i-1,l-1}-s_{i-1,m-r}) ]

    然后只考虑把(g_{i,r})的转移式给写开:

    [egin{align} g_{i,r}&=sum_{l=1}^rf_{i,l,r}\ &=sum_{l=1}^rw_{l,r} imes(s_{i-1,m}-s_{i-1,l-1}-s_{i-1,m-r})\ &=q_{m-r} imes((sum_{l=1}^rq_{l-1}) imes(s_{i-1,m}-s_{i-1,m-r})-sum_{l=1}^{r}q_{l-1} imes s_{i-1,l-1}) end{align} ]

    于是只要在枚举(r)的同时维护好(sum_{l=1}^rq_{l-1})(sum_{l=1}^{r}q_{l-1} imes s_{i-1,l-1})就可以直接转移了。

    最终的答案显然就是(s_{n,m})

    代码:(O(nm))

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 1500
    #define K 100000
    #define X 1000000007
    #define C(x,y) (1LL*Fac[x]*IFac[y]%X*IFac[(x)-(y)]%X)//组合数
    using namespace std;
    int n,m,k,p,q[K+5],f[2][N+5][N+5],g[N+5][N+5],s[N+5][N+5];
    I int QP(RI x,RI y) {RI t=1;W(y) y&1&&(t=1LL*t*x%X),x=1LL*x*x%X,y>>=1;return t;}
    int Fac[N+K],IFac[K+5];I void InitFac()//预处理阶乘和阶乘逆元
    {
    	RI i;for(Fac[0]=i=1;i<=k;++i) Fac[i]=1LL*Fac[i-1]*i%X;
    	for(IFac[i=k]=QP(Fac[k],X-2);i;--i) IFac[i-1]=1LL*IFac[i]*i%X;
    }
    int main()
    {
    	RI i,j,x,y;scanf("%d%d%d%d%d",&n,&m,&x,&y,&k),p=1LL*x*QP(y,X-2)%X,InitFac();
    	for(i=0;i<=k;++i) q[i]=1LL*C(k,i)*QP(p,i)%X*QP((1-p+X)%X,k-i)%X;//预处理k次中恰好成功i次的概率
    	for(g[0][m]=s[0][m]=i=1;i<=n;++i)//枚举每一行DP
    	{
    		for(x=y=j=0;j<=m;x=(x+q[j])%X,y=(1LL*q[j]*s[i-1][j]+y)%X,++j)//枚举j同时维护好和
    			g[i][j]=1LL*q[m-j]*(1LL*x*(s[i-1][m]-s[i-1][m-j]+X)%X-y+X)%X;//转移
    		for(s[i][0]=g[i][0],j=1;j<=m;++j) s[i][j]=(s[i][j-1]+g[i][j])%X;//对g前缀和求出s
    	}return printf("%d
    ",s[n][m]),0;
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    git查日志命令
    使用git把本地目录传到远程仓库
    本地ssh设置多个git项目访问
    php的phar是什么?
    .ssh免密登录问题解决
    idea配置tomcat时,运行按钮灰色禁用状态
    idea快捷键main,print,代码提示
    windows安装hadoop找不到JAVA_HOME
    spring boot 启动时找不到主类
    jquery 删除自己
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/CF708E.html
Copyright © 2011-2022 走看看