题目大意:给你一个n*m的网格图,每个位置是0或者1,每次你可以选择一个1*2的子矩形涂黑。问期望多少次后所有1位置都被涂黑了?每次选择是独立的。
n
≤
6
,
m
≤
100
n\le6,m\le100
n≤6,m≤100。
题解:
考虑Min-Max容斥,问题转为对每个1的子集T求第一次覆盖到T中某个1的概率,这个就是总方案数分之有多少方案至少一端在T中,用类似轮廓线的方法dp这个即可。(一开始写了直接状压的做法,代码附在后面)
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Rep(i,v) rep(i,0,(int)v.size()-1)
#define lint long long
#define mod 998244353
#define ull unsigned lint
#define db long double
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define gc getchar()
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
typedef pair<int,int> pii;
typedef set<int>::iterator sit;
inline int inn()
{
int x,ch;while((ch=gc)<'0'||ch>'9');
x=ch^'0';while((ch=gc)>='0'&&ch<='9')
x=(x<<1)+(x<<3)+(ch^'0');return x;
}
const int N=10,M=110;
char str[N][M];
inline int fast_pow(int x,int k,int ans=1) { for(;k;k>>=1,x=(lint)x*x%mod) (k&1)?ans=(lint)ans*x%mod:0;return ans; }
inline int upd(int &x,int y) { return x+=y,(x>=mod?x-=mod:0); }
inline int sol(int x,int z) { return (z&1)?(x?mod-x:0):x; }
namespace subtask345{
const int N=8,MXS=70,M=110;
int dp[2][N][MXS][M*N*2][2],inv[N*M*2],up[M][N];
inline int acceptable_solution(int n,int m)
{
int all=(1<<n)-1,tot=2*m*n-m-n;
rep(i,1,m)
{
up[i][0]=up[i-1][n];
rep(j,1,n)
{
up[i][j]=up[i][j-1];
if(j>1&&(str[j][i]=='*'||str[j-1][i]=='*')) up[i][j]++;
if(i>1&&(str[j][i]=='*'||str[j][i-1]=='*')) up[i][j]++;
// debug(i)sp,debug(j)sp,debug(up[i][j])ln;
}
}
dp[1][0][0][0][0]=1;
rep(i,1,m)
{
#define now dp[i&1]
#define nxt dp[(i+1)&1]
rep(j,1,n) rep(s,0,all) rep(k,0,up[i][j]) rep(t,0,1) now[j][s][k][t]=0;
rep(j,0,n-1) rep(s,0,all) rep(k,0,up[i][j]) rep(t,0,1) if(now[j][s][k][t])
{
upd(now[j+1][s^(s&(1<<j))][k+((s>>j)&1)+(j?((s>>(j-1))&1):0)][t],now[j][s][k][t]);
if(str[j+1][i]=='*') upd(now[j+1][s|(1<<j)][k+(i>1)+(j>0)][t^1],now[j][s][k][t]);
}
rep(s,0,all) rep(k,0,up[i][n]) rep(t,0,1) nxt[0][s][k][t]=now[n][s][k][t];
#undef now
#undef nxt
}
#define now dp[m&1]
int ans=0;rep(c,1,up[m][n]) inv[c]=fast_pow(c,mod-2);
rep(s,0,all) rep(c,1,up[m][n]) rep(t,0,1)
if(now[n][s][c][t]) upd(ans,sol((lint)inv[c]*now[n][s][c][t]%mod,t^1));
return !printf("%lld\n",(lint)ans*tot%mod);
#undef now
}
}
int main()
{
int n=inn(),m=inn();rep(i,1,n) scanf("%s",str[i]+1);
return subtask345::acceptable_solution(n,m);return 0;
}
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Rep(i,v) rep(i,0,(int)v.size()-1)
#define lint long long
#define mod 998244353
#define ull unsigned lint
#define db long double
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define gc getchar()
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
typedef pair<int,int> pii;
typedef set<int>::iterator sit;
inline int inn()
{
int x,ch;while((ch=gc)<'0'||ch>'9');
x=ch^'0';while((ch=gc)>='0'&&ch<='9')
x=(x<<1)+(x<<3)+(ch^'0');return x;
}
const int N=10,M=110;
char str[N][M];
inline int fast_pow(int x,int k,int ans=1) { for(;k;k>>=1,x=(lint)x*x%mod) (k&1)?ans=(lint)ans*x%mod:0;return ans; }
inline int upd(int &x,int y) { return x+=y,(x>=mod?x-=mod:0); }
inline int sol(int x,int z) { return (z&1)?(x?mod-x:0):x; }
namespace subtask345{
const int N=8,MXS=70,M=110;
int dp[M][MXS][2*N*M][2],sz[MXS],ok[M][MXS],calc[M][MXS];
int inv[2*N*M];
inline int acceptable_solution(int n,int m)
{
int all=(1<<n)-1,tot=2*n*m-n-m;
rep(i,1,all) sz[i]=sz[i>>1]+(i&1);
rep(i,1,m)
{
int t=0;
rep(j,1,n) if(str[j][i]=='*') t|=(1<<(j-1));
rep(s,0,all) if((s&t)==s)
{
ok[i][s]=1;
rep(j,1,n-1) if(((s>>(j-1))&1)||((s>>j)&1)) calc[i][s]++;
}
}
dp[0][0][0][0]=1;
rep(i,0,m-1)
{
#define now dp[i]
#define nxt dp[i+1]
rep(s,0,all) rep(j,0,2*(i+1)*n-i-1-n) rep(k,0,1) nxt[s][j][k]=0;
int up=(i?2*i*n-i-n:0);
rep(s,0,all) rep(j,0,up) rep(k,0,1)
if(now[s][j][k]) rep(t,0,all) if(ok[i+1][t])
{
int nj=j+(i?sz[s|t]:0)+calc[i+1][t],nk=k^(sz[t]&1);
upd(nxt[t][nj][nk],now[s][j][k]);
}
#undef now
#undef nxt
}
#define now dp[m]
int ans=0;rep(i,1,tot) inv[i]=fast_pow(i,mod-2);
rep(s,0,all) rep(c,1,tot) rep(k,0,1) if(now[s][c][k])
upd(ans,sol((lint)inv[c]*now[s][c][k]%mod,k^1));
ans=(lint)ans*tot%mod;return !printf("%d\n",ans);
#undef now
}
}
int main()
{
int n=inn(),m=inn();rep(i,1,n) scanf("%s",str[i]+1);
return subtask345::acceptable_solution(n,m);return 0;
}