记 R i R_i Ri表示第 i i i行元素异或和, L i L_i Li表示第 i i i列元素异或和。那么矩阵全为零时显然 L i , R i L_i,R_i Li,Ri全为零。
如果 n n n, m m m都是偶数,那么每次操作 ( i , j ) (i,j) (i,j)相当于把 L k ( k ≠ i ) L_k(k\ne i) Lk(k=i) 和 R k ( k ≠ j ) R_k(k\ne j) Rk(k=j) 翻转。我们可以看成只对 L i , R j L_i,R_j Li,Rj翻转,这又相当于只翻转 ( i , j ) (i,j) (i,j)这一个点,因此任意 01 01 01矩阵都是可以还原的。
如果 n n n是奇数, m m m是偶数,那么操作 ( i , j ) (i,j) (i,j)相当于把 L k ( k ≠ i ) L_k(k\ne i) Lk(k=i)和所有 R k R_k Rk翻转,发现只和 i i i有关,结论是 R k R_k Rk必须全为 0 0 0或全为 1 1 1。
求方案数则对于每个右部点钦定一条边即可。
如果 n , m n,m n,m都是奇数,那么操作 ( i , j ) (i,j) (i,j)相当于把所有 L k L_k Lk和 R k R_k Rk翻转,于是结论很明显,必须初始全为 0 0 0或全为 1 1 1。
至于计数部分,如果 ( i , j ) (i,j) (i,j)是问号就在二分图上连一条边,对于一个连通块要对每条边定 0 / 1 0/1 0/1边权使点权满足奇偶性。可以考虑构建生成树,对于不在生成树上的边可以随便定,对于在生成树上的边的边权是唯一确定的。
#include<bits/stdc++.h>
#define fi first
#define se second
#define ll long long
#define pb push_back
#define db double
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
const int mod=998244353;
int n,m,K,W,num,vis[4005],in[4005],L[2005],R[2005];
int V,E;
char s[2005][2005];
vector<int>g[4005];
ll fpow(ll x,ll y){
ll z(1);for(;y;y>>=1){
if(y&1)z=z*x%mod;
x=x*x%mod;
}return z;
}
void dfs(int u){
vis[u]=num,V++;
W^=(u<=n)?L[u]:R[u-n];
for(auto v:g[u]){
if(!vis[v]){
dfs(v);
}if(u<=n&&vis[v]==num)E++;
}
}
ll solve(int f){
ll res=1;
for(int i=1;i<=n+m;i++)vis[i]=0;
for(int i=1;i<=n+m;i++){
if(!vis[i]){
num++,V=E=W=0,dfs(i);
if(W!=f*V%2)return 0;
res=res*fpow(2,E-V+1)%mod;
}
}return res;
}
ll solve1(int f){
int c=0;
for(int i=1;i<=m;i++){
if(R[i]!=f&&!in[n+i]){
return 0;
}if(in[n+i])c++;
}return fpow(2,K-c);
}
ll solve2(int f){
int c=0;
for(int i=1;i<=n;i++){
if(L[i]!=f&&!in[i]){
return 0;
}if(in[i])c++;
}
return fpow(2,K-c);
}
int main(){
cin>>n>>m;for(int i=1;i<=n;i++){
scanf("%s",s[i]+1);
for(int j=1;j<=m;j++){
if(s[i][j]=='1')L[i]^=1,R[j]^=1;
if(s[i][j]=='?')in[i]++,in[n+j]++,K++,g[i].pb(n+j),g[n+j].pb(i);
}
}
if(n%2==0&&m%2==0){
cout<<fpow(2,K);
}
else if(n%2==1&&m%2==0){
cout<<(solve1(0)+solve1(1))%mod;
}
else if(n%2==0&&m%2==1){
cout<<(solve2(0)+solve2(1))%mod;
}
else {
cout<<(solve(0)+solve(1))%mod;
}
}