网格染色 [组合计数]
的网格图, 给任意多个网格染色, 计算 使得每行每列至少有一个染色网格 的 染色方案数 .
答案 每 列 都合法的总方案数 列 合法前提下 行 不合法的方案数 .
每 列 都合法的总方案数 , 行 不合法的方案数 .
.
#include<bits/stdc++.h>
#define reg register
const int maxn = 1e6 + 5;
const int mod = 998244353;
int N;
int M;
int pw[maxn];
int inv[maxn];
int fac[maxn];
int ifac[maxn];
char S[maxn];
int C(int n, int m){ return 1ll*fac[n]*ifac[m]%mod*ifac[n-m]%mod; }
int Ksm(int a, int b){
int s = 1;
while(b){
if(b & 1) s = 1ll*s*a % mod;
a = 1ll*a*a % mod; b >>= 1;
}
return s;
}
int main(){
scanf("%d%d", &N, &M);
scanf("%s", S+1); int t = N;
for(reg int i = 1; i <= t; i ++) if(S[i] == '.') N --;
scanf("%s", S+1); t = M;
for(reg int i = 1; i <= t; i ++) if(S[i] == '.') M --;
inv[1] = 1; for(reg int i = 2; i <= std::max(N, M); i ++) inv[i] = ((-1ll*mod/i*inv[mod%i])%mod + mod) % mod;
fac[0] = 1; for(reg int i = 1; i <= std::max(N, M); i ++) fac[i] = 1ll*fac[i-1]*i%mod;
ifac[0] = 1; for(reg int i = 1; i <= std::max(N, M); i ++) ifac[i] = 1ll*ifac[i-1]*inv[i] % mod;
pw[0] = 1; for(reg int i = 1; i <= std::max(N, M); i ++) pw[i] = 2ll*pw[i-1] % mod;
int Ans = 0;
for(reg int i = 0; i <= N; i ++){
int add = 1ll*C(N, i)*Ksm(pw[N-i]-1, M)%mod;
if(i & 1) add = -add;
Ans = ((Ans + add)%mod + mod) % mod;
}
printf("%d\n", Ans);
return 0;
}