Problem:
Score : 800 points

Problem Statement

There is a square grid with N rows and M columns.
Each square contains an integer: 0 or 1. The square at the i-th row from the top and the j-th column from the left contains a_{ij}.

Among the 2^{N+M} possible pairs of a subset A of the rows and a subset B of the columns, find the number of the pairs that satisfy the following condition, modulo 998244353:

The sum of the |A||B| numbers contained in the intersection of the rows belonging to A and the columns belonging to B, is odd.

Constraints

1 \leq N,M \leq 300

0 \leq a_{i,j} \leq 1(1\leq i\leq N,1\leq j\leq M)

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N M
a_{11} ... a_{1M}
:
a_{N1} ... a_{NM}

Output

Print the number of the pairs of a subset of the rows and a subset of the columns that satisfy the condition, modulo 998244353.

Sample Input 1

2 2
0 1
1 0

Sample Output 1

6

For example, if A consists of the first row and B consists of both columns, the sum of the numbers contained in the intersection is 0+1=1.

Sample Input 2

2 3
0 0 0
0 1 0

Sample Output 2

8

Solution in PyPy3 (2.4.0) (judge verdict: Time Limit Exceeded)

class GE():
    def __init__(self, A, mod):
        self.N = len(A)
        self.M = len(A[0])
        self.A = A[:]
        self.mod = mod
        self.uptri = None
        self.pivot = []
        self.R = None
        
    def ut(self):
        if self.uptri is not None:
            return self.uptri
        self.uptri = self.A[:]
        
        c = 0
        for i in range(self.N):
            if i + c >= self.M:
                break
            while self.uptri[i][i+c] == 0:
                for j in range(i+1, self.N):
                    if self.uptri[j][i+c]:
                        self.uptri[i], self.uptri[j] = self.uptri[j], self.uptri[i]
                        break
                else:
                    c += 1
                    if i + c == self.M:
                        return self.uptri
            self.pivot.append((i, i+c))
            t = pow(self.uptri[i][i+c], self.mod - 2, self.mod)
            for j in range(i+1, self.N):
                tj = t * self.uptri[j][i+c]
                self.uptri[j][i+c:] = [(aj - tj*ai) % self.mod for ai, aj in zip(self.uptri[i][i+c:], self.uptri[j][i+c:])]
            for pi, pj in self.pivot[::-1]:
                t = pow(self.uptri[pi][pj], self.mod-2, self.mod)
                self.uptri[pi][pj:] = [(ai * t) % self.mod for ai in self.uptri[pi][pj:]]
                for i in range(pi-1, -1, -1):
                    ti = self.uptri[i][pj]
                    self.uptri[i][pj:] = [(ai - api*ti) % self.mod for ai, api in zip(self.uptri[i][pj:], self.uptri[pi][pj:])]
        
        return self.uptri
    def rank(self):
        if self.R is not None:
            return self.R
        self.ut()
        self.R = len(self.pivot)
        return self.R

N, M = map(int, input().split())
A = [list(map(int, input().split())) for _ in range(N)]
mod = 998244353
T = GE(A, 2)
print((pow(2, N+M-1, mod) - pow(2, N+M-T.rank()-1, mod)) % mod)