一看数据范围我以为要插头DP。
然后发现不维护连通性的插头DP不是随便打吗。。。。。。
直接
m
i
n
−
m
a
x
min-max
min−max反演。
求
E
(
∑
T
⊂
S
(
−
1
)
∣
T
∣
+
1
min
(
T
)
)
=
∑
T
⊂
S
(
−
1
)
∣
T
∣
+
1
E
(
min
(
T
)
)
E(\sum_{T\sub S} (-1)^{|T|+1}\min(T)) = \sum_{T\sub S} (-1)^{|T|+1}E(\min(T))
E(∑T⊂S(−1)∣T∣+1min(T))=∑T⊂S(−1)∣T∣+1E(min(T))
其中
S
S
S代表喜欢的礼物的集合。
然后我们发现
E
(
min
(
T
)
)
=
(
n
−
1
)
m
+
n
(
m
−
1
)
包
含
T
中
任
意
一
个
礼
物
的
相
邻
格
子
对
数
E(\min(T))=\frac {(n-1)m+n(m-1)}{包含T中任意一个礼物的相邻格子对数}
E(min(T))=包含T中任意一个礼物的相邻格子对数(n−1)m+n(m−1)
所以我们以(包含T中任意一个礼物的相邻格子对数)为一维状态插头
D
P
DP
DP,求包含T中任意一个礼物的相邻格子对数
=
i
= i
=i时的容斥系数
d
p
i
dp_i
dpi
那么
∑
T
⊂
S
(
−
1
)
∣
T
∣
+
1
E
(
min
(
T
)
)
=
∑
i
=
1
(
n
−
1
)
m
+
n
(
m
−
1
)
d
p
i
(
(
n
−
1
)
m
+
n
(
m
−
1
)
)
i
\sum_{T\sub S}(-1)^{|T|+1} E(\min(T)) = \sum_{i=1}^{(n-1)m+n(m-1)}\frac {dp_i((n-1)m+n(m-1))}{i}
∑T⊂S(−1)∣T∣+1E(min(T))=∑i=1(n−1)m+n(m−1)idpi((n−1)m+n(m−1))
#include<bits/stdc++.h>
#define mod 998244353
using namespace std;
int n,m;char s[7][105];
int f[2][1206][1<<7],inv[1206]={1,1};
void add(int &a,int b){ a=(a+b) % mod; }
int main(){
scanf("%d%d",&n,&m);int N = (1<<n+1) , M = (n-1)*m+n*(m-1);
for(int i=1;i<=n;i++) scanf("%s",s[i]);
int now = 1 , pre = 0;
f[now][0][N-1] = -1;
for(int i=0;i<m;i++) for(int j=1;j<=n;j++){
swap(now,pre);
for(int p=0;p<=M;p++) for(int k=0;k<N;k++) if(f[pre][p][k]){
add(f[now][p][j == n ? (((k&(N-1-(1<<j-1)-(1<<j)))<<1|1)&(N-1)) : (k&(N-1-(1<<j-1)-(1<<j)))] , f[pre][p][k]);
if(s[j][i] == '*')
add(f[now][p+((k&(1<<j-1))==0)+((k&(1<<j))==0)+(i!=m-1)+(j!=n)][j == n ? (((k|(1<<j-1)|(1<<j))<<1|1)&(N-1)) : (k|(1<<j-1)|(1<<j))] , -f[pre][p][k]);
f[pre][p][k] = 0;
}
}
for(int i=2;i<=M;i++) inv[i] = 1ll * (mod - mod / i) * inv[mod % i] % mod;
int ans = 0;
for(int i=1;i<=M;i++) for(int j=0;j<N;j++) if(f[now][i][j])
ans = (ans + 1ll * f[now][i][j] * inv[i] % mod * M) % mod;
printf("%d\n",(ans+mod)%mod);
}