{-# LANGUAGE
  ScopedTypeVariables, BangPatterns, TupleSections, ExplicitForAll,
  LambdaCase, MultiWayIf, Unsafe, RecordWildCards, FlexibleContexts, CPP,
  NoMonomorphismRestriction, GADTs,
  RankNTypes, EmptyDataDecls, EmptyCase, ViewPatterns #-}

import Data.Bits
import Data.List
import qualified Data.ByteString.Char8 as BS
import qualified Data.ByteString.Lazy.Char8 as BSL
import Data.IntMap.Strict (IntMap)
import qualified Data.IntMap.Strict as IMS
import qualified Data.IntMap.Lazy as IML
import Data.IntSet (IntSet)
import qualified Data.IntSet as IS
import qualified Data.Sequence as Seq
import Data.Sequence (Seq)
import qualified Data.Array.IArray as A
import qualified Data.Array.MArray.Safe as A
import qualified Data.Array.MArray as A
import Data.Array (Array)
import Data.Array.Unboxed (UArray)
import Data.Array.IArray (IArray)
import Data.Array.MArray.Safe (MArray)
import Data.Array.IO.Safe (IOArray, IOUArray)
import Data.Array.ST.Safe (STArray, STUArray, runSTArray, runSTUArray)
import qualified Data.Vector as V
import qualified Data.Vector.Unboxed as VU
import qualified Data.Vector.Unboxed.Mutable as VUM
import Control.Monad
import Control.Monad.ST
-- import Control.Monad.ST.Safe
import Control.Applicative
import Data.Maybe
import Data.Tuple
import Data.Ord
import Control.Monad.State.Strict
import Data.Int
import Data.Word
import System.IO
import Data.Function
import Control.Monad.Primitive
import qualified Data.Vector.Primitive.Mutable as VPM
import qualified Data.Vector.Generic.Mutable as VGM
import Data.STRef
import Data.IORef

main :: IO ()
main = do
  [n,m] <- map readInt . words <$> getLine
  a_ <-  map (==1) . unfoldr (runStateT $ rInt) <$> BSL.getContents
  let rank = countRank n m a_
  print $ fromMon $ 2^(n+m-1) - 2^(n+m-rank-1)
      

{-# INLINE countRank #-}
countRank :: Int -> Int -> [Bool] -> Int
countRank n m a_ = runST $ do
  a <- A.newListArray ((0,0),(n-1,m-1)) a_ :: ST s (STUArray s (Int,Int) Bool)
  check <- newSTUA (0,n-1) True
  foldM (\ !acc j -> do
            colj <- forM [0..n-1] $ \i ->
              (&&) <$> A.readArray a (i,j) <*> A.readArray check i
            case findIndex id colj of
              Nothing -> return acc
              Just i -> do
                A.writeArray check i False 
                forM_ [0..n-1] $ \i1 ->
                  when (i /= i1) $ do
                  ai1j <- A.readArray a (i1,j)
                  when ai1j $ do
                    forM_ [j..m-1] $ \j1 -> do
                      A.writeArray a (i1,j1) =<<
                        xor <$> A.readArray a (i1,j1) <*> A.readArray a (i,j1)
                return $! acc+1 
                 ) 0 [0..m-1]
              
            
  

{-# INLINE modulus #-}
modulus :: (Integral i) => i
modulus = 998244353

{-# INLINE nprime #-}
nprime :: Word64
nprime = 998244351

{-# INLINE rsq #-}
rsq :: Word64
rsq = 932051910

newtype Montgomery = Mon {unMon :: Word32}
  deriving (Eq, Show)

instance Num Montgomery where
  {-# INLINE (+) #-}
  (+) = monAdd
  {-# INLINE (*) #-}
  (*) = monMult
  {-# INLINE (-) #-}
  (-) = monSub
  {-# INLINE negate #-}
  negate (Mon x) = Mon (modulus - x)
  {-# INLINE fromInteger #-}
  fromInteger = monRep . fromInteger
  {-# INLINE signum #-}
  signum x | x == Mon 0 = Mon 0
           | otherwise  = monRep 1
  {-# INLINE abs #-}
  abs = id

{-# INLINE monMult #-}
monMult :: Montgomery -> Montgomery -> Montgomery
monMult (Mon x) (Mon y) = Mon $ monRed $ fromIntegral x * fromIntegral y

{-# INLINE monAdd #-}
monAdd :: Montgomery -> Montgomery -> Montgomery
monAdd (Mon x) (Mon y) = Mon $ x+y + if x >= modulus-y then modulus else 0
    
{-# INLINE monSub #-}
monSub :: Montgomery -> Montgomery -> Montgomery
monSub (Mon x) (Mon y) = Mon $ x-y + if x < y then modulus else 0

{-# INLINE monRep #-}
monRep :: Word32 -> Montgomery
monRep x = Mon $ monRed $ rsq * fromIntegral x

{-# INLINE fromMon #-}
fromMon :: Montgomery -> Word32
fromMon (Mon x) = monRed $ fromIntegral x

{-# INLINE monRed #-}
monRed :: Word64 -> Word32
monRed x = t - if t >= modulus then modulus else 0
  where t = fromIntegral $ (`shiftR` 32) $ x + x*nprime .&.mask32 *modulus

mask32 :: Word64
mask32 = bit 32 - 1


rInt :: StateT BSL.ByteString Maybe Int
rInt = StateT $ BSL.readInt . BSL.dropWhile (<'!')

#define D(f,r,d) f::Integral a=>a->d;f=fromIntegral;r::String->d;r=read
#define C(f,r,g,h,d) D(f,r,d);g,h::RealFrac a=>a->d;g=floor;h=ceiling
C(_toInteger_,readInteger,floorInteger,ceilInteger,Integer)
C(toInt,readInt,floorInt,ceilInt,Int)
C(toI8,readI8,floorI8,ceilI8,Int8)
C(toI16,readI16,floorI16,ceilI16,Int16)
C(toI32,readI32,floorI32,ceilI32,Int32)
C(toI64,readI64,floorI64,ceilI64,Int64)
C(toWord,readWord,floorWord,ceilWord,Word)
C(toW8,readW8,floorW8,ceilW8,Word8)
C(toW16,readW16,floorW16,ceilW16,Word16)
C(toW32,readW32,floorW32,ceilW32,Word32)
C(toW64,readW64,floorW64,ceilW64,Word64)
D(toDouble,readDouble,Double)
D(toFloat,readFloat,Float)
#undef D
#undef C


#define N(f,g,a,m)\
  f :: forall e i s. (C(a,m)A.Ix i) => (i,i) -> e -> m (a i e); f=A.newArray;\
  g :: forall e i s. (C(a,m)A.Ix i) => (i,i) -> m (a i e); g=A.newArray_
#define C(a,m)
N(newIOA,newIOA_,IOArray,IO)
N(newSTA,newSTA_,STArray s,ST s)
#undef C
#define C(a,m) MArray (a) e (m), 
N(newIOUA,newIOUA_,IOUArray,IO)
N(newSTUA,newSTUA_,STUArray s,ST s)
#undef C
#undef N



Measured memory_bytes: 1148