def op(x, y): return x|y class UnionFind: def __init__(self, n, A, op): self.n = n self.parent_size = [-1]*n self.A = A[:] self.op = op def leader(self, a): if self.parent_size[a] < 0: return a self.parent_size[a] = self.leader(self.parent_size[a]) return self.parent_size[a] def merge(self, a, b): x, y = self.leader(a), self.leader(b) if x == y: return l, r = self.A[x], self.A[y] if abs(self.parent_size[x]) < abs(self.parent_size[y]): x, y = y, x self.parent_size[x] += self.parent_size[y] self.parent_size[y] = x self.A[x] = self.op(l, r) return def __getitem__(self, n): return self.A[self.leader(n)] def update(self, n, a): self.A[self.leader(n)] = a def same(self, a, b): return self.leader(a) == self.leader(b) def size(self, a): return abs(self.parent_size[self.leader(a)]) def groups(self): result = [[] for _ in range(self.n)] for i in range(self.n): result[self.leader(i)].append(i) return [r for r in result if r != []] MOD = 998244353 H, W = map(int, input().split()) A = [list(map(int, input().split())) for _ in range(H)] POW = [1] for _ in range(H+W): POW.append(POW[-1]*2%MOD) B = sorted([(i, j, A[i][j]) for i in range(H) for j in range(W)], key=lambda x:x[2], reverse=True) rank = [[-1]*W for _ in range(H)] IDX = [-1]*H for idx, (i, j, a) in enumerate(B): rank[i][j] = idx if IDX[i] == -1: IDX[i] = j FH = [False]*H cntH = H UF = [UnionFind(W, [0]*W, op) for _ in range(H)] cnt = [W]*H ans = 0 for i, j, a in B: if not FH[i]: FH[i] = True cntH -= 1 if UF[i][j] == 0: cnt[i] -= 1 flag = UF[i][j] == 0 UF[i].update(j, 1) if flag: ans += a*POW[cntH+cnt[i]]%MOD ans %= MOD if IDX[i] != j and not UF[0].same(IDX[i], j): for k in range(H): if UF[k][IDX[i]] == 0 or UF[k][j] == 0: cnt[k] -= 1 UF[k].merge(IDX[i], j) print(ans)