zoukankan      html  css  js  c++  java
  • 5.19 省选模拟赛 小B的夏令营 概率 dp 前缀和优化dp

    LINK:小B的夏令营

    avatar
    avatar

    这道题是以前从没见过的优化dp的方法 不过也在情理之中.

    注意读题 千万不要像我这个sb一样 考完连题意都不知道是啥.

    一个长方形 要求从上到下联通的概率。

    容易发现 K天只是用来计算概率的 和 dp的状态无关。

    我们可以逐行 dp.

    容易设f[i][l][r]表示前i行 当前行l~r没有被摧毁的概率。

    考虑在k天之后第i行 l~r没被摧毁的概率。

    l-1在这k天被摧毁了 那么因为有序 概率为(C(k,l-1)p^{l-1}(1-p)^{k-l+1})

    对于r的那边同理。

    暴力转移 就是枚举上一层的L,R 使得L~R与l~r的交集不为空.

    整个时间复杂度为n^5.

    考虑 快速得到L~R 对 l~r的贡献 发现 求和l~r有交比较困难。

    考虑容斥 那么就是总-左端点在r之后-右端点在l之前即可。

    这样就可以优化到n^3 值得注意的是 上述两种情况其实是对等的 所以只需要求一种即可。

    inline int mul(int a,int b){return (ll)a*b%mod;}
    inline int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
    inline int mux(int a,int b){return a-b<0?a-b+mod:a-b;}
    const int MAXN=510,maxn=100010;
    int n,m,p,k;
    int f[2][MAXN][MAXN];
    int fac[maxn],inv[maxn],w[maxn],w1[MAXN];
    inline int ksm(int b,int p)
    {
    	int cnt=1;
    	while(p){if(p&1)cnt=mul(cnt,b);b=mul(b,b);p=p>>1;}
    	return cnt;
    }
    inline void prepare(int maxx)
    {
    	fac[0]=1;
    	rep(1,maxx,i)fac[i]=mul(fac[i-1],i);
    	inv[maxx]=ksm(fac[maxx],mod-2);
    	fep(maxx-1,0,i)inv[i]=mul(inv[i+1],i+1);
    }
    inline int C(int a,int b){return a<b?0:(ll)fac[a]*inv[b]%mod*inv[a-b]%mod;}
    int main()
    {
    	freopen("b.in","r",stdin);
        freopen("b.out","w",stdout);
    	get(n);get(m);p=(ll)read()*ksm(read(),mod-2)%mod;get(k);
    	prepare(max(n,k));
    	rep(0,min(k,m),i)w[i]=mul(mul(C(k,i),ksm(p,i)),ksm(1-p+mod,k-i));
    	int u=0;f[u][1][m]=1;
    	rep(1,n,T)
    	{
    		int ans=0;
    		rep(1,m,i)w1[i]=0;
    		rep(1,m,i)rep(i,m,j)
    		{
    			ans=add(ans,f[u][i][j]);
    			w1[j]=add(w1[j],f[u][i][j]);
    		}
    		rep(1,m,i)w1[i]=add(w1[i],w1[i-1]);
    		u=u^1;
    		rep(1,m,i)rep(i,m,j)
    		f[u][i][j]=mul(mux(mux(ans,w1[i-1]),w1[m-j]),mul(w[i-1],w[m-j]));
    	}
    	int ans=0;
    	rep(1,m,i)rep(i,m,j)ans=add(ans,f[u][i][j]);
    	put(ans);
    	return 0;
    }
    

    考虑100分的做法:

    状态的维度都是n^3的 必须要降维.

    按行划分是必要的 所以只能把左端点给省掉或者把右端点给省掉.

    我是将前者省掉 设状态f[i][j]表示到了第i行 以j为右端点的概率。

    这次需要先枚举l进行转移 实际上这个枚举可以经过预处理之后O(1)得到。

    所以 复杂度被降到了nm.

    值得注意的是 需要把状态转移方程给写清楚 然后考虑预处理哪些项来计算。

    不要像我一样迷瞪半天...

    inline int mul(int a,int b){return (ll)a*b%mod;}
    inline int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
    inline int mux(int a,int b){return a-b<0?a-b+mod:a-b;}
    const int MAXN=1510,maxn=100010;
    int n,m,p,k;
    int f[MAXN][MAXN];//f[i][j]表示前i行 右端点在j的概率.
    int fac[maxn],inv[maxn],w[maxn],w1[maxn],w2[maxn];
    inline int ksm(int b,int p)
    {
    	int cnt=1;
    	while(p){if(p&1)cnt=mul(cnt,b);b=mul(b,b);p=p>>1;}
    	return cnt;
    }
    inline void prepare(int maxx)
    {
    	fac[0]=1;
    	rep(1,maxx,i)fac[i]=mul(fac[i-1],i);
    	inv[maxx]=ksm(fac[maxx],mod-2);
    	fep(maxx-1,0,i)inv[i]=mul(inv[i+1],i+1);
    }
    inline int C(int a,int b){return a<b?0:(ll)fac[a]*inv[b]%mod*inv[a-b]%mod;}
    int main()
    {
    	freopen("b.in","r",stdin);
        freopen("b.out","w",stdout);
    	get(n);get(m);p=(ll)read()*ksm(read(),mod-2)%mod;get(k);
    	prepare(max(n,k));
    	rep(0,min(k,m),i)w[i]=mul(mul(C(k,i),ksm(p,i)),ksm(1-p+mod,k-i));
    	f[0][m]=1;
    	rep(1,n,i)
    	{
    		int ww1=0;int cnt=0;int cc=0;
    		rep(1,m,j)
    		{
    			cnt=add(cnt,f[i-1][j]);
    			ww1=add(ww1,f[i-1][j]);
    			w1[j]=add(w1[j-1],mul(w[j],ww1));
    			w2[j]=ww1;
    		}
    		rep(1,m,j)
    		{
    			cc=add(cc,w[j-1]);
    			f[i][j]=mux(mux(mul(cc,cnt),w1[j-1]),mul(cc,w2[m-j]));
    			f[i][j]=mul(f[i][j],w[m-j]);
    		}
    	}
    	int ans=0;
    	rep(1,m,i)ans=add(ans,f[n][i]);
    	put(ans);
    	return 0;
    }
    
  • 相关阅读:
    Apache 虚拟主机 VirtualHost 配置
    EAX、ECX、EDX、EBX寄存器的作用
    Python中文文档 目录(转载)
    八度
    POJ 3268 Silver Cow Party (最短路)
    POJ 2253 Frogger (求每条路径中最大值的最小值,Dijkstra变形)
    2013金山西山居创意游戏程序挑战赛——复赛(1) HDU 4557 非诚勿扰 HDU 4558 剑侠情缘 HDU 4559 涂色游戏 HDU 4560 我是歌手
    HDU 4549 M斐波那契数列(矩阵快速幂+欧拉定理)
    UVA 11624 Fire! (简单图论基础)
    HDU 3534 Tree (树形DP)
  • 原文地址:https://www.cnblogs.com/chdy/p/12924492.html
Copyright © 2011-2022 走看看