{-# LANGUAGE BangPatterns #-} import Control.Monad import Control.Monad.ST import Data.STRef import qualified Data.Vector.Fusion.Stream.Monadic as VFSM import qualified Data.Vector.Unboxed.Mutable as VUM import GHC.Exts stream :: Monad m => Int -> Int -> VFSM.Stream m Int stream !l !r = VFSM.Stream step l where step x | x < r = return $ VFSM.Yield x (x + 1) | otherwise = return $ VFSM.Done {-# INLINE [0] step #-} {-# INLINE [1] stream #-} rep1 :: Monad m => Int -> (Int -> m ()) -> m () rep1 n = flip VFSM.mapM_ (stream 1 (n + 1)) rep2 :: Monad m => Int -> (Int -> m ()) -> m () rep2 n = flip VFSM.mapM_ (stream 2 (n + 1)) main :: IO () main = readLn >>= print . solver solver :: Int -> Int solver n = runST $ do as <- VUM.unsafeNew 202020 bs <- VUM.unsafeNew 202020 ss <- newSTRef (1 :: Int) rep1 n $ \i -> modifySTRef' ss (\s -> s * i `mod` 998244353) VUM.unsafeWrite as 0 (1 :: Int) VUM.unsafeWrite bs 0 (1 :: Int) rep2 n $ \i -> do itemA1 <- VUM.unsafeRead as (i - 1) itemA2 <- VUM.unsafeRead as (i - 2) VUM.unsafeWrite as i ((i - 1) * (itemA1 + itemA2) `mod` 998244353) when (i >= 4) $ do if even i then do itemb1 <- VUM.unsafeRead bs (i - 1) itemb4 <- VUM.unsafeRead bs (i - 4) VUM.unsafeWrite bs i (((i - 1) * itemb1 + 2 * (i - 2) * itemb4) `mod` 998244353) else do itemb1 <- VUM.unsafeRead bs (i - 1) itemb2 <- VUM.unsafeRead bs (i - 2) VUM.unsafeWrite bs i (((i - 1) * itemb1 + 2 * (i - 1) * itemb2) `mod` 998244353) item0 <- readSTRef ss item1 <- VUM.unsafeRead as n item2 <- VUM.unsafeRead bs n return $ flip mod 998244353 $ item0 - item1 - item1 + item2 + 998244353 + 998244353