#include #include #include #include using namespace std; struct UF{ vector par,sz; vector f; UF(int n){ sz.resize(n); par.resize(n); f.resize(n); for(int i=0;isz[y]) swap(x,y); sz[y] += sz[x]; f[y] = (f[y]|f[x]); par[x] = y; } void check(int x){f[find(x)] = true;} bool ff(int x){return f[find(x)];} bool same(int x,int y){return find(x)==find(y);} }; typedef long long ll; ll mod = 998244353; ll a[1010][1010]; ll pw(ll a,ll x){ ll ret = 1; while(x){ if(x&1) (ret *= a) %= mod; (a *= a) %= mod; x /= 2; } return ret; } int main(){ int i,j,h,w; cin >> h >> w; vector v; for(i=0;i> a[i][j]; v.push_back(a[i][j]); } } sort(v.rbegin(),v.rend()); v.erase(unique(v.begin(),v.end()),v.end()); map>> mp; for(i=0;i ans(v.size()); int sz = h + w - 2,k = 0; for(int val:v){ for(auto p:mp[val]){ int i = p.first,j = p.second; j += h; if(i==0 || j==h){ if(!i){ if(!uf.ff(j)) sz--; uf.check(j); }else{ if(!uf.ff(i)) sz--; uf.check(i); } }else{ if((!uf.ff(i) || !uf.ff(j)) && !uf.same(i,j)) sz--; uf.unite(i,j); } } ans[k++] = pw(2,sz) - 1; } UF uf2(2*(h + w)); sz = h + w - 2,k = 0; bool f = true; for(int val:v){ if(a[0][0]==val) f = false; for(auto p:mp[val]){ int i = p.first,j = p.second; j += h; if(i==0 || j==h){ if(!i){ if(!uf2.ff(j)) sz--; uf2.check(j); if(uf2.ff(j + h + w - 1)) f = false; }else{ if(!uf2.ff(i)) sz--; uf2.check(i); if(uf2.ff(i + h + w - 1)) f = false; } }else{ bool f1 = uf2.ff(i) || uf2.ff(i + h + w - 1); bool f2 = uf2.ff(j) || uf2.ff(j + h + w - 1); if((!f1 || !f2) && !uf2.same(i,j + h + w - 1)) sz--; uf2.unite(i,j + h + w - 1); uf2.unite(i + h + w - 1,j); if(uf2.same(i,i + h + w - 1)) f = false; if(uf2.same(j,j + h + w - 1)) f = false; if(uf2.ff(i) && uf2.ff(j)) f = false; } } if(f) (ans[k++] += pw(2,sz)) %= mod; else (ans[k++] += 0) %= mod; } // for(i=0;i