zoukankan      html  css  js  c++  java
  • CF708E Student's Camp

    CF708E Student's Camp [* easy]

    有一个 (n imes m) 的矩形。

    每天两种操作,持续 (k) 天:

    • 所有最左边的方块有 (p) 的概率消失。
    • 所有最右边的方块有 (p) 的概率消失。

    然后我们在最顶部和最底部增加一层,如果某个时刻,此图分成了两个联通分量,那么就 GG。

    求不 GG 的概率。答案对 (10^9+7) 取模。

    (n,mle 1500,kle 10^5)

    Solution

    考虑给每一行确定一个区间,合法当且仅当每个区间都和上一个区间相交。

    (f_{i,l,r}) 表示考虑到第 (i) 行,区间为 ([l,r]) 的概率和,由于 ([l,r]) 的长度大于等于 (1),所以这件事发生的概率可以视为左边走到 (l),右边走到 (r) 的概率的乘积,即 (p_l imes p_r)

    考虑转移,形如:

    [f_{i,l,r}=p_lp_r imes sum f_{i-1,l',r'}([l',r']land [l,r]) ]

    这样难以优化,考虑减去不相交的区间,那么后者只关乎区间的 (r) 端点,设 (F_{i,R}=sum f_{i,l,r}[rle R],G_{i,L}=sum f_{i,l,r}[lge L])

    不难得到:

    [f_{i,l,r}=p_lp_r(sum f-F_{i-1,l-1}-G_{i-1,r+1}) ]

    然而复杂度还是太高了,考虑直接转移 (g_{i,r'}=sum f_{i,l,r}[r=r']),那么就有:

    [g_{i,r}=p_r(sum p_l(sum f-F_{i-1,l-1}-G_{i-1,r+1})) ]

    [g_{i,r}=p_r(sum p_l)(sum f-G_{i-1,r+1})-p_rsum p_lF_{i-1,l-1} ]

    [f_{i,l}=p_l(sum p_r)(sum f-F_{i-1,l-1})-p_lsum p_rG_{i-1,r+1} ]

    然后就可以算 (G) 了,类似处理 (F) 即可。

    复杂度 (mathcal O(nm))

    (Code:)

    #include<bits/stdc++.h>
    using namespace std ;
    #define Next( i, x ) for( register int i = head[x]; i; i = e[i].next )
    #define rep( i, s, t ) for( register int i = (s); i <= (t); ++ i )
    #define drep( i, s, t ) for( register int i = (t); i >= (s); -- i )
    #define re register
    #define int long long
    int gi() {
    	char cc = getchar() ; int cn = 0, flus = 1 ;
    	while( cc < '0' || cc > '9' ) {  if( cc == '-' ) flus = - flus ; cc = getchar() ; }
    	while( cc >= '0' && cc <= '9' )  cn = cn * 10 + cc - '0', cc = getchar() ;
    	return cn * flus ;
    }
    const int P = 1e9 + 7 ; 
    const int N = 1500 + 5 ; 
    const int M = 1e5 + 5 ; 
    int n, m, p, ip, t, h[N], H[N], F[N][N], G[N][N] ;
    int f[N][N], g[N][N], pl[N], pr[N], fac[M], inv[M] ; 
    int fpow(int x, int k) {
    	if( k < 0 ) return 0 ; 
    	int ans = 1, base = x ;
    	while(k) {
    		if(k & 1) ans = 1ll * ans * base % P ;
    		base = 1ll * base * base % P, k >>= 1 ;
    	} return ans ;
    }
    int C(int x, int y) {
    	if(y > x || x < 0 || y < 0) return 0 ;
    	return fac[x] * inv[y] % P * inv[x - y] % P ; 
    }
    signed main()
    {
    	n = gi(), m = gi() ; int x, y ; 
    	x = gi(), y = gi(), p = x * fpow(y, P - 2) % P,
    	t = gi(), fac[0] = inv[0] = 1, ip = (1 - p + P) % P ; 
    	rep( i, 1, t ) fac[i] = fac[i - 1] * i % P, inv[i] = fpow(fac[i], P - 2) ; 
    	rep( i, 1, m ) 
    		pl[i] = C(t, i - 1) * fpow(p, i - 1) % P * fpow(ip, t - (i - 1)) % P, 
    		pr[i] = C(t, m - i) * fpow(p, m - i) % P * fpow(ip, t - (m - i)) % P ;
    	
    	H[0] = 1 ; 
    	rep( i, 1, n ) {
    		int k = H[i - 1], d = 0, df = 0 ;
    		rep( r, 1, m ) {
    			d = (d + pl[r]) % P, df = (df + pl[r] * G[i - 1][r - 1]) % P,
    			g[i][r] = pr[r] * d % P * (k - F[i - 1][r + 1] + P) % P,
    			g[i][r] = (g[i][r] - pr[r] * df % P + P) % P ; //1/8
    			//1/8
    		}
    		d = 0, df = 0 ; 
    		for(re int l = m; l >= 1; -- l ) {
    			d = (d + pr[l]) % P, df = (df + pr[l] * F[i - 1][l + 1]) % P, 
    			f[i][l] = pl[l] * d % P * (k - G[i - 1][l - 1] + P) % P, 
    			f[i][l] = (f[i][l] - pl[l] * df % P + P) % P ;
    		}
    		rep( r, 1, m ) G[i][r] = (G[i][r - 1] + g[i][r]) % P ;
    		drep( l, 1, m ) F[i][l] = (F[i][l + 1] + f[i][l]) % P ; 
    		H[i] = G[i][m] ;
    	}
    	cout << H[n] << endl ; 
    	return 0 ;
    }
    
  • 相关阅读:
    Yahoo军规
    简单无序列表
    PS切图基本操作
    Web Service 系列 → 智能升级也简单(用Web Services制作升级程序)
    PHP 模板引擎 Smarty
    C# 哈希表(Hashtable)
    ASP.NET 备份与恢复ACCESS数据库
    开源的C#组件 RSS.NET
    Discuz!NT 的URL地址重写(URLRewrite)
    C# SquishIt JavaScript、CSS压缩器
  • 原文地址:https://www.cnblogs.com/Soulist/p/13781585.html
Copyright © 2011-2022 走看看