• 【UOJ#422】【集训队作业2018】小Z的礼物(min-max容斥,轮廓线dp)


    【UOJ#422】【集训队作业2018】小Z的礼物(min-max容斥,轮廓线dp)

    题面

    UOJ

    题解

    毒瘤xzy,怎么能搬这种题当做WC模拟题QwQ
    一开始开错题了,根本就不会做。
    后来发现是每次任意覆盖相邻的两个,那么很明显就可以套(min-max)容斥。
    要求的就是(max(All)),而每个集合的(min)是很好求的。
    如果直接暴力枚举集合复杂度就是(2^{cnt}cnt)
    仔细想想每个子集我们要知道的是什么,只需要知道子集大小来确定前面的容斥系数,还需要知道覆盖子集的方案数,这样就可以知道(min)的概率,倒数就是期望了。
    而覆盖子集的方案数不会超过(2*n*m-n-m),显然要比(2^{cnt})优秀。
    所以枚举覆盖子集的方案数来(dp),至于子集大小之和容斥系数相关,而容斥系数只有正负(1),所以直接乘进去一起转移就好了,不需要单独存一维状态。
    考虑每次新加入一个点之后的覆盖方案,只需要知道当前位置四周是否已经存在于子集当中,那么直接状压当前的轮廓线就好了。
    设状态(f[S][k])表示覆盖方案数为(k),轮廓线为(S)时的方案数,容斥系数已经考虑进去。
    显然当前位置可以不选,那么直接转移。
    如果当前位置可以选入子集,那么乘上系数(-1),同时修改覆盖方案数以及轮廓线的状态转移。
    最后按照(min-max)容斥统计答案即可。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    #define MOD 998244353
    void add(int &x,int y){x+=y;if(x>=MOD)x-=MOD;}
    char g[200][200];
    int n,m,inv[1500],sum,pw,nw,ans,S;
    int f[2][1<<6][1200];
    int main()
    {
    	scanf("%d%d",&n,&m);S=1<<n;sum=2*n*m-n-m;
    	for(int i=1;i<=n;++i)scanf("%s",g[i]+1);
    	inv[0]=inv[1]=1;for(int i=2;i<1500;++i)inv[i]=1ll*inv[MOD%i]*(MOD-MOD/i)%MOD;
    	f[0][0][0]=MOD-1;
    	for(int i=1;i<=m;++i)
    		for(int j=1;j<=n;++j)
    		{
    			pw=nw;nw^=1;memset(f[nw],0,sizeof(f[nw]));
    			for(int T=0;T<S;++T)
    				for(int k=0;k<=sum;++k)
    					if(f[pw][T][k])
    					{
    						int nT=T&((S-1)^(1<<(j-1)));
    						add(f[nw][nT][k],f[pw][T][k]);
    						if(g[j][i]=='*')
    						{
    							nT|=1<<(j-1);int pls=0;
    							if(j>1&&!(T&(1<<(j-2))))++pls;
    							if(i>1&&!(T&(1<<(j-1))))++pls;
    							if(i<m)++pls;if(j<n)++pls;
    							add(f[nw][nT][k+pls],MOD-f[pw][T][k]);
    						}
    					}
    		}
    	for(int T=0;T<S;++T)
    		for(int i=1;i<=sum;++i)
    			add(ans,1ll*f[nw][T][i]*inv[i]%MOD);
    	ans=1ll*ans*sum%MOD;printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    Webpack 学习2
    Webpack 学习
    JS魔法堂:彻底理解0.1 + 0.2 === 0.30000000000000004的背后
    JS魔法堂:再识Number type
    基础野:细说浮点数
    基础野:细说有符号整数
    基础野:细说无符号整数
    基础野:细说原码、反码和补码
    Vim魔法堂:认识快捷键绑定
    Httpd运维日志:通过apxs添加模块
  • 原文地址:https://www.cnblogs.com/cjyyb/p/10216412.html
Copyright © 2020-2023  润新知