• CF708E Student's Camp


    CF708E Student's Camp

    传送门

    CodeForces

    题解

    我莫得脑子

    首先可以设(f_{i,l,r})表示现在到了第(i)行,还剩下第(l ightarrow r)个砖块,而且整个图联通的概率.

    这里设

    [D_i=inom{t}{i}{p}^i(1-p)^{t-i} \ ]

    很明显有

    [f_{i,l,r}=sum_{max(l',l)<=min(r',r)}D(l-1)D(m-r)f_{i-1,l',r'} ]

    这样子转移是(O(nm^4))的,很明显会(GG).

    这里我们再设(P(l,r)=D(l-1)D(m-r+1))

    考虑优化,正难则反,即我们考虑转移的时候用所有的减去不合法的,即:

    [f_{i,l,r}=P(l,r)(sum_{l'<=r'}f_{i-1,l',r'}-sum_{r'<l}f_{i-1,l',r'}-sum_{l'>r}f_{i-1,l',r'}) ]

    这里就变成了三个(sum)的计数,一个一个考虑.

    [F(i)=sum_{l<=r}f_{i,l,r} \ L(i,x)=sum_{r<x}f_{i,l,r} \ R(i,x)=sum_{l>x}f_{i,l,r} ]

    这个时候转移就可以写成:

    [f_{i,l,r}=P(l,r)[F(i-1)-L(i-1,l)-R(i-1,r)] ]

    不难发现(L_{i,x}=R_{i,m-x+1}),所以我们只需要考虑(L)的更简单的求法.

    我们可以钦定

    [Sl_{i,r}=sum_{l<=r}f_{i,l,r} ]

    这个时候就有:

    [F(i)=sum_{r=1}^mSl_{i,r} \ L(i,x)=sum_{r<x}Sl_{i,r} \ R(i,x)=L(i,m-x+1)=sum_{r<m-x+1}Sl_{i,r} ]

    接着考虑回带,即:

    [egin{align} Sl_{i,r}&=sum_{l<=r}f_{i,l,r} \ &=sum_{l<=r}P(l,r)[F(i-1)-sum_{r=1}^{x-1}Sl_{i-1,r}-sum_{r=1}^{m-x}Sl_{i-1,r}] \ &=D(m-r)sum_{l=1}^{r}D(l-1)[F(i-1)-R(i-1,r)]-D(l-1)L(i-1,l) end{align} ]

    这样子转移即可.初始值(Sl_{0,m}=1),答案是(F(n)).

    代码

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<math.h>
    #include<algorithm>
    #include<queue>
    #include<set>
    #include<map>
    #include<iostream>
    using namespace std;
    #define ll long long
    #define REP(a,b,c) for(int a=b;a<=c;a++)
    #define re register
    #define file(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
    typedef pair<int,int> pii;
    #define mp make_pair
    inline int gi()
    {
    	int f=1,sum=0;char ch=getchar();
    	while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
    	return f*sum;
    }
    const int N=2010,M=100010,Mod=1e9+7;
    int n,m,p,t,fac[M],inv[M],ifac[M],Sl[N][N],S1[M],S2[N][N],L[N][N],D[N];
    int C(int n,int m){if(n<m||m<0||n<0)return 0;return 1ll*fac[n]*ifac[m]%Mod*ifac[n-m]%Mod;}
    int qpow(int a,int b){int ret=1;while(b){if(b&1)ret=1ll*ret*a%Mod;b>>=1;a=1ll*a*a%Mod;}return ret;}
    int main()
    {
    	n=gi();m=gi();p=gi();p=1ll*p*qpow(gi(),Mod-2)%Mod;t=gi();
    	fac[0]=ifac[0]=inv[0]=inv[1]=ifac[1]=fac[1]=1;
    	for(int i=2;i<=100000;i++)fac[i]=1ll*fac[i-1]*i%Mod,inv[i]=1ll*(Mod-Mod/i)*inv[Mod%i]%Mod,ifac[i]=1ll*ifac[i-1]*inv[i]%Mod;
    	for(int i=0;i<=min(m,t);i++)D[i]=1ll*C(t,i)*qpow(p,i)%Mod*qpow((1-p+Mod),t-i)%Mod;
    	for(int i=1;i<=m;i++)S1[i]=(S1[i-1]+D[i-1])%Mod;
    	Sl[0][m]=1;L[0][m]=1;
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++)
    		{
    			Sl[i][j]=1ll*D[m-j]*(1ll*(L[i-1][m]-L[i-1][m-j]+Mod)*S1[j]%Mod-S2[i-1][j]+Mod)%Mod;
    			L[i][j]=(L[i][j-1]+Sl[i][j])%Mod;
    			S2[i][j]=(S2[i][j-1]+1ll*D[j-1]*L[i][j-1]%Mod)%Mod;
    		}
    	printf("%d
    ",L[n][m]);
    	return 0;
    }
    
  • 相关阅读:
    set, unordered_set模板类
    C/C++ Bug记录
    win10远程连接
    C/C++缓冲区刷新问题
    hihocoder1711 评论框排版[并查集+set]
    makefile
    Virtual Table
    粤语
    xilinx SDK开发 GPIO使用API总结
    基于zynq 7020的串口UART中断实验
  • 原文地址:https://www.cnblogs.com/fexuile/p/12849856.html
Copyright © 2020-2023  润新知