• UOJ422 【集训队作业2018】小Z的礼物


    题目

    不难发现我们要求的是一个(E(max(S))),这看起来比较困难,于是我们直接上min-max容斥,如果我们枚举了一个集合(T),集合(T)中有(t)对相邻格子,那么对答案的贡献就是((-1)^{|T|+1}frac{2nm-n-m}{t})

    于是我们搞一个状压轮廓线的dp,设(dp_{i,j,s,k})表示当前处理的格子是((i,j)),轮廓线状态为(s),选出了(k)对相邻格子,刷表转移即可

    代码

    #include<bits/stdc++.h>
    #define re register
    const int mod=998244353;
    inline int dqm(int x) {return x<0?x+mod:x;}
    inline int upd(int &x,int y) {x+=y;if(x>=mod)x-=mod;}
    int dp[2][(1<<6)+1][1200],inv[1200],ans,n,m;
    char ma[105][105];
    int main() {
    	scanf("%d%d",&n,&m);int S=2*n*m-n-m,nS=0,len=(1<<n);--len;inv[1]=1;
    	for(re int i=2;i<=S;i++) inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
    	for(re int i=1;i<=n;i++) scanf("%s",ma[i]+1);
    	dp[0][0][0]=mod-1;int o=0;
    	for(re int i=1;i<=m;i++)
    		for(re int j=1;j<=n;j++) {
    			memset(dp[o^1],0,sizeof(dp[o^1]));
    			for(re int s=0;s<=len;++s)
    				for(re int k=0;k<=nS;++k) {
    					if(!dp[o][s][k]) continue;
    					upd(dp[o^1][s&(len^(1<<(j-1)))][k],dp[o][s][k]);
    					if(ma[j][i]=='*') {
    						int det=0;
    						if(i>1&&!(s>>(j-1)&1)) det++;
    						if(j>1&&!(s>>(j-2)&1)) det++;
    						if(j<n) ++det;if(i<m) ++det; 
    						upd(dp[o^1][s|(1<<(j-1))][k+det],dqm(mod-dp[o][s][k]));
    						if(k+det>nS) nS=k+det;
    					}
    				}
    			o^=1;
    		} 
    	int ans=0;
    	for(re int s=0;s<=len;++s)
    		for(re int k=0;k<=S;++k) upd(ans,1ll*dp[o][s][k]*inv[k]%mod);
    	printf("%d
    ",1ll*ans*S%mod);return 0;
    }
    
  • 相关阅读:
    git学习笔记
    ubuntu常用命令
    hdfs[命令] fsck
    hdfs[命令] dfsadmin
    hdfs[命令] dfs
    Hadoop2.0新特性-持续追加【干货】
    Cloudera 建议使用 NTP 使 Hadoop 群集实现时间同步
    Cloudera CDH5 部署实战指南(离线安装)
    没有用户画像,别谈精准营销
    用户画像数据建模方法
  • 原文地址:https://www.cnblogs.com/asuldb/p/12102407.html
Copyright © 2020-2023  润新知