• uoj#422. 【集训队作业2018】小Z的礼物(MIn-Max容斥+插头dp)


    题面

    传送门

    题解

    好迷……

    很明显它让我们求的是(Max(S)),我们用(Min-Max)容斥,因为(Min(S))是很好求的,只要用方案数除以总方案数算出概率,再求出倒数就是期望了

    然而如果爆搜枚举子集的话复杂度是(O(2^{cnt}))

    发现总共的方案数只有(2*n*m-n-m)种,而且(n)非常小,我们可以考虑插头(dp)

    (f_{i,S,k})表示做到了第(i)列,插头的状态为(S),覆盖方案数为(k)时的方案总数,并且这个里面已经考虑了容斥系数

    然后直接转移就是了

    //minamoto
    #include<bits/stdc++.h>
    #define R register
    #define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i)
    #define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i)
    #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
    using namespace std;
    const int N=1505,P=998244353;
    inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;}
    inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
    inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
    char s[N][N];int f[2][(1<<6)+5][N],inv[N],g[N];
    int n,m,t,G,sum,tmp,res;
    int main(){
    //	freopen("testdata.in","r",stdin);
    	scanf("%d%d",&n,&m),G=(1<<n)-1;
    	fp(i,0,n-1)scanf("%s",s[i]);
    	sum=n*m*2-n-m;
    	inv[0]=inv[1]=1;fp(i,2,sum)inv[i]=mul(P-P/i,inv[P%i]);
    	f[0][0][0]=P-1,t=0;
    	fp(j,0,m-1)fp(i,0,n-1){
    		memset(f[t^1],0,sizeof(f[t^1]));
    		fp(S,0,G)fp(k,0,sum)if(f[t][S][k]){
    			int T=S&(G^(1<<i));
    			f[t^1][T][k]=add(f[t^1][T][k],f[t][S][k]);
    			if(s[i][j]=='*'){
    				T|=1<<i;
    				tmp=(i&&!(S&(1<<(i-1))))+(j&&!(S&(1<<i)))+(i<n-1)+(j<m-1);
    				f[t^1][T][k+tmp]=add(f[t^1][T][k+tmp],P-f[t][S][k]);
    			}
    		}
    		t^=1;
    	}
    	fp(S,0,G)fp(i,1,sum)res=add(res,mul(f[t][S][i],inv[i]));
    	res=mul(res,sum);printf("%d
    ",res);
    	return 0;
    }
    
  • 相关阅读:
    原生JS---2
    PHP中include和require绝对路径、相对路径问题
    魔方(小玩具)
    html5技术介绍
    苹果电脑 快捷键
    写代码的心得,怎么减少编程中的 bug?
    http状态代码含义表
    开源项目
    蓝牙 CoreBluetooth
    减小iOS应用程序的大小
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/10467731.html
Copyright © 2020-2023  润新知