#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <string>
#include <sstream>
#include <complex>
#include <vector>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <map>
#include <set>
using namespace std;
 
#define mod 998244353
#define FOR(x,to) for(int x=0;x<(to);x++)
#define FORR(x,arr) for(auto& x:arr)
#define ALL(a) (a.begin()),(a.end())
#define ZERO(a) memset(a,0,sizeof(a))
#define MINUS(a) memset(a,0xff,sizeof(a))
#define long long long
inline int rei(){int x;cin>>x;return x;}
inline long rel(){long x;cin>>x;return x;}
inline string res(){string x;cin>>x;return x;}
//------------------------------------------------------- 
class MTwo{
public:
    using t = bool;
    static t id() {
        return false;
    }
	static t e() {
        return true;
    }
	// * 
    static t op1(const t& l, const t& r){
        return l && r;
    }
	// + 
	static t op2(const t& l, const t& r){
        return l ^ r;
    }
	// - 
	static t op3(const t& x){
        return x;
    }
	// /
	static t op4(const t& x) {
        return x;
    }
};
template< typename M >
struct Matrix{
	using T = typename M::t;
	int H;
	int W;
	vector<T> data;
    Matrix(int n_)
        : H(n_), W(n_), data(n_ * n_, M::id()) {}
    Matrix(int h_, int w_)
        : H(h_), W(w_), data(h_ * w_, M::id()) {}
	Matrix(int n_,vector<T> d_)
        : H(n_), W(n_) {data = d_;}
    Matrix(int h_, int w_, vector<T> d_)
        : H(h_), W(w_) {data = d_;}
  	void Update(int h,int w,T x){
    	data[h*W+w] = x;
  	}
  	const T Get(int h,int w){
    	return data[h*W+w];
  	}
	int Rank(){
		int ans = 0;
		vector<T> A(H*W);
		vector<bool> used(H);
		for(int i=0;i<H*W;i++){
			A[i] = data[i];
		}
		for(int i=0;i<W;i++){
			int nonzero = 0;
			while(nonzero < H && (used[nonzero] || A[nonzero*W+i] == M::id())){
				nonzero++;
			}
			if(nonzero == H){
				continue;
			}
			ans++;
			used[nonzero] = true;
			for(int j=0;j<H;j++){
				if(used[j]){
					continue;
				}
				T d = M::op3(M::op1(M::op4(A[nonzero*W+i]),A[j*W+i])); 
				for(int k=i;k<W;k++){
					A[j*W+k] = M::op2(A[j*W+k],M::op1(A[nonzero*W+k],d));
				}
			}
		}	
		return ans;
	}
	static Matrix I(int N){
		Matrix ans(N);
		for(int i=0;i<N;i++){
			ans.Update(i,i,M::e());
		}
		return ans;
	}
	static Matrix Plus(Matrix& A,Matrix& B){
		int h = A.H;
		int w = A.W;
		Matrix ans(h,w);
		for(int i=0;i<h;i++){
			for(int j=0;j<w;j++){
				ans.Update(i,j,M::op2(A.Get(i,j),B.Get(i,j)));
			}
		}
		return ans;
	}
	static Matrix Minus(Matrix& A){
		int h = A.H;
		int w = A.W;
		Matrix ans(h,w);
		for(int i=0;i<h;i++){
			for(int j=0;j<w;j++){
				ans.Update(i,j,M::op3(A.Get(i,j)));
			}
		}
		return ans;
	}
	static Matrix Minus(Matrix& A,Matrix& B){
		int h = A.H;
		int w = A.W;
		Matrix ans(h,w);
		for(int i=0;i<h;i++){
			for(int j=0;j<w;j++){
				ans.Update(i,j,M::op2(A.Get(i,j),M::op3(B.Get(i,j))));
			}
		}
		return ans;
	}
	static Matrix Prod(Matrix& A,Matrix& B){
		int h = A.H;
		int w = B.W;
		int K = A.W;
		Matrix ans(h,w);
		for(int i=0;i<h;i++){
			for(int j=0;j<w;j++){
				T c = M::id();
				for(int k=0;k<K;k++){
					c = M::op2(c,M::op1(A.Get(i,k),B.Get(k,j)));
				}
				ans.Update(i,j,c);
			}
		}
		return ans;
	}
	static Matrix Pow(Matrix A,long r){
		int n = A.H;
		Matrix ans = I(n);
		while(r){
			if(r % 2 == 1){
				ans = Prod(ans,A);
			}
			A = Prod(A,A);
			r /= 2;
		}
		return ans;
	}
};
void Calc(){
	int N = rei();
	int M = rei();
	vector<bool> A(N*M);
	for(int i=0;i<N;i++){
		for(int j=0;j<M;j++){
			int x = rei();
			A[i*M+j] = x % 2 == 1;
		}
	}
	Matrix<MTwo> mat(N,M,A);
	int r = mat.Rank();
	long ans1 = 1;
	long ans2 = 1;
	for(int i=0;i<N+M-1;i++){
		ans1 *= 2;
		ans1 %= mod;
	}
	for(int i=0;i<N+M-r-1;i++){
		ans2 *= 2;
		ans2 %= mod;
	}
	cout << (ans1 - ans2 + mod) % mod << endl;
}
int main(int argc,char** argv){
	ios::sync_with_stdio(false), cin.tie(0);
	cout.tie(0); Calc(); return 0;
}

Measured memory_bytes: 256