There is a square matrix n × n, consisting of non-negative integer numbers. You should find such a way on it that   starts in the upper left cell of the matrix;  each following cell is to the right or down from the current cell;  the way ends in the bottom right cell. Moreover, if we multiply together all the numbers along the way, the result should be the least "round". In other words, it should end in the least possible number of zeros.

The first line contains an integer number n (2 ≤ n ≤ 1000), n is the size of the matrix. Then follow n lines containing the matrix elements (non-negative integer numbers not exceeding 109).

In the first line print the least number of trailing zeros. In the second line print the correspondent way itself.

module Main where

import Data.Array.IArray
import qualified Data.Array as A
import Data.List (foldl')
import qualified Data.ByteString.Char8 as B

scanl' :: (a -> b -> a) -> a -> [b] -> [a]
scanl' _ z  []    = [z]
scanl' f z (x:xs) = let u = f z x
                        ys = z:scanl' f u xs
                    in u `seq` ys `seq` ys

powerOf :: Int -> Int -> Int
powerOf _ 0 = error "powerOf 0"
powerOf p n = case n `mod` p of
  0 -> 1 + powerOf p (n `div` p)
  _ -> 0

data DP = DP { isZero :: !Bool
             , minNum :: !Int
             , go :: !String }
             deriving (Show)

dpCost :: DP -> Int
dpCost (DP True  _ _) = 1
dpCost (DP False c _) = c

dp :: Int -> Int -> [[Int]] -> DP
dp n p (row:rows) = (foldl' (dpRow n p) (dpFirstRow n p row) rows)!(n-1)

dpRow :: Int -> Int -> A.Array Int DP -> [Int] -> A.Array Int DP
dpRow n p ups (cur:curs) = listArray (0,n-1) $ scanl' step dpInit (zip [1..] curs) where
  step (DP _        _       leftGo) (i, 0)
                        = DP True 1 ('R':leftGo)
  step (DP leftZero leftNum leftGo) (i, k)
    | upCost < leftCost = DP upZero   upCost   ('D':upGo)
    | otherwise         = DP leftZero leftCost ('R':leftGo)
    where DP upZero upNum upGo = ups!i
          k' = powerOf p k
          upCost = if upZero then 1 else k' + upNum
          leftCost = if leftZero then 1 else k' + leftNum
  dpInit = case cur of
            0 -> DP True 1 ('D':go up)
            k -> DP False (powerOf p k + minNum up) ('D':go up)
  up = ups!0

dpFirstRow :: Int -> Int -> [Int] -> A.Array Int DP
dpFirstRow n p currs = listArray (0,n-1) $ zipWith zipper costs rs where
  zipper (dpZero, cost) dir = DP dpZero cost dir
  costs = tail $ scanl' step (False, 0) currs
  step (True, _)    _ = (True, 1)
  step (_,    cost) 0 = (True, 1)
  step (_,    cost) k = (False, cost + powerOf p k)
  rs = iterate ('R':) []

inputGrids :: IO (Int, [[Int]])
inputGrids = do
  n <- readLn
  grids <- sequence $ replicate n $ do
    line <- B.getLine
    return $ map (maybe (error "Read") fst) . map B.readInt . B.words $ line
  return (n, grids)

main :: IO ()
main = do
  (n, grids) <- inputGrids
  let dp2 = dp n 2 grids
      dp5 = dp n 5 grids
  if dpCost dp2 <= dpCost dp5
    then (print . dpCost $ dp2) >> (putStrLn . reverse . go $ dp2)
    else (print . dpCost $ dp5) >> (putStrLn . reverse . go $ dp5)

{-# LANGUAGE BangPatterns #-}

import Control.Monad
import Data.Array
import qualified Data.Array as A
import qualified Data.Array.Unboxed as U
import qualified Data.ByteString as B
import qualified Data.ByteString.Char8 as B8
import Data.List
import Debug.Trace
import Control.Monad.ST
import Data.Array.ST

data Path = PathUp | PathLeft | NoPath
	deriving (Show, Eq)
--data Cell = Cell !Int !Path -- Cost Path
--	deriving (Show)

--cost (Cell c _) = c

decide up left = if up == noVal
		then if left == 0 then PathLeft else PathUp
		else if left == noVal
			then if up == 0 then PathUp else PathLeft
			else if left <= up then PathLeft else PathUp

path (i, j) arr
	| (i == 1) && (j == 1) = NoPath
	| (i == 1) && (j > 1) = PathUp
	| (i > 1) && (j == 1) = PathLeft
	| (i > 1) && (j > 1) = decide up left
		where
			up = arr ! (i, j - 1)
			left = arr ! (i - 1, j)

noVal = -1

getInput = do
	n <- (liftM read) getLine
	lines <- sequence $ replicate n B.getLine
	let arr = map (B.split 0x20) lines
	return $! (n, U.array ((1, 1), (n, n)) [((i, j), v) | (line, j) <- (zip arr [1..n]), (num, i) <- (zip line [1..n]), let !v = readNumber num])
	where
		readNumber x = case B8.readInt x of
			Just (!num, _) -> num
			Nothing -> error "Unable to read input"

calcPaths :: U.Array (Int, Int) Int -> Int -> Int -> Array (Int, Int) Int
calcPaths arr n divisor = runSTArray $ do
	a <- newArray ((1, 1), (n, n)) 0 :: ST s (STArray s (Int,Int) Int)
	forM_ [1..n] $! \diag -> do
		let indices = diagIndices $! diag
		forM_ indices $! \(i, j) -> case () of
			_ | (i == 1) && (j == 1) -> writeArray a (i, j) current
				| (i == 1) && (j > 1) -> do
					up <- readArray a (i, j - 1)
					writeArray a (i, j) $! normalize current up
				| (i > 1) && (j == 1) -> do
					left <- readArray a (i - 1, j)
					writeArray a (i, j) $! normalize current left
				| (i > 1) && (j > 1) -> do
					up <- readArray a (i, j - 1)
					left <- readArray a (i - 1, j)
					writeArray a (i, j) $! if decide up left == PathLeft
						then normalize current left
						else normalize current up
				where
					current = if (arr U.! (i, j) /= 0)
						then powerOf divisor (arr ! (i, j))
						else noVal
	return a
	where
		normalize !value !addend = (if value == noVal || addend == noVal then noVal else value + addend)
		diagIndices diag = if diag == n then [(diag, diag)] else
			zip [diag..n] (repeat diag) ++ zip (repeat diag) [(diag + 1)..n]

powerOf :: Int -> Int -> Int
powerOf q p = powerOf' q p 0
	where
		powerOf' q p n = if p `mod` q /= 0 then n else powerOf' q (p `div` q) (n + 1)

getPath arr n = reverse $ getPath' (n, n)
	where
		getPath' (i, j)
			| (i, j) == (1, 1) = ""
			| otherwise = if path (i,j) arr == PathUp
				then 'D' : getPath' (i, j - 1)
				else 'R' : getPath' (i - 1, j)

main = do
	(n, matrix) <- getInput
	let paths2 = calcPaths matrix n 2
	let cost2 = (paths2 ! (n, n))
	path2 <- do
		return $ getPath paths2 n

	let paths5 = calcPaths matrix n 5
	let cost5 = (paths5 ! (n, n))
	path5 <- do
		return $ getPath paths5 n

	if abs cost2 < abs cost5
		then do
			if cost2 < 0 then print 1 else print cost2
			putStrLn path2
		else do
			if cost5 < 0 then print 1 else print cost5
			putStrLn path5

import qualified Data.ByteString.Char8 as B
import Data.List (foldl')
import Data.Array.IArray
import Data.Array.ST.Safe (STArray,STUArray,newArray,readArray,writeArray)
import Data.STRef (newSTRef,readSTRef,writeSTRef)
import Control.Monad (when)
import Control.Monad.ST.Safe (ST,runST)
main = do
  (n:ns) <- fmap (map read' . B.words) B.getContents
  let prep = do
        m2 <- newArray (0,n) (maxBound `div` 2) :: ST s (STUArray s Int Int)
        p2 <- newArray (0,n) "E"                :: ST s (STArray s Int String)
        writeArray m2 1 0
        writeArray p2 1 ""
        return (m2,p2)
  let dp ns = runST $ do
        zero <- newSTRef Nothing
        (m2,p2) <- prep
        (m5,p5) <- prep
        let dp' ns = go ns 1 where
              go [] _ = return ()
              go (x:xs) i = do
                when (x == 0) $ writeSTRef zero (Just i)
                l2  <- readArray m2 (i-1)
                l2p <- readArray p2 (i-1)
                l5  <- readArray m5 (i-1)
                l5p <- readArray p5 (i-1)
                u2  <- readArray m2  i
                u2p <- readArray p2  i
                u5  <- readArray m5  i
                u5p <- readArray p5  i
                let n2 = factors 2 x
                    n5 = factors 5 x
                    (e2,e2p) = min ((l2+n2),('R':l2p)) ((u2+n2),('D':u2p))
                    (e5,e5p) = min ((l5+n5),('R':l5p)) ((u5+n5),('D':u5p))
                writeArray m2 i e2
                writeArray p2 i e2p
                writeArray m5 i e5
                writeArray p5 i e5p
                go xs $! i+1
        mapM_ dp' ns
        b2  <- readArray m2 n
        b2p <- readArray p2 n
        b5  <- readArray m5 n
        b5p <- readArray p5 n
        z <- readSTRef zero
        let (m,p) = min (b2,b2p) (b5,b5p)
        return $ case z of
          Nothing -> (m,p)
          Just j -> min (m,p) (1,replicate (n-j) 'R' ++
                                 replicate (n-1) 'D' ++
                                 replicate (j-1) 'R' ++ "E")
      (m,p) = dp (chunksOf n ns)
  print m
  putStrLn (tail $ reverse p)
{-# INLINE factors #-}
factors _ 0 = 1
factors n x = go x 0 where
  go x a | r == 0    = go q $! a + 1
         | otherwise = a
    where (q,r) = x `divMod` n
{-# INLINE chunksOf #-}
chunksOf n = go where
  go [] = []
  go xs = l : go r where (l,r) = splitAt n xs
{-# INLINE read' #-}
read' s = r where Just (r,_) = B.readInt s

{-# LANGUAGE DerivingVia #-}
module Main where

import Data.List (foldl')

import qualified Data.Array.IArray as I
import qualified Data.Array as A
import qualified Data.ByteString.Char8 as B

import Control.Monad (forM_, replicateM)
import Data.Functor ((<&>))
import Data.Semigroup (Sum(..))
import Data.Ord (comparing)
import Data.Maybe (fromJust)
import Data.Word
import GHC.List (scanl')

type V = Int

main :: IO ()
main = do
  Answer w p <- solve <$> readInput
  print (unWeight w)
  putStrLn (reverse p)

readInput :: IO [[V]]
readInput = do
    n <- readLn
    replicateM n $ B.getLine <&> forced . readLine
  where
    readLine = map (fst . fromJust . B.readInt) . B.words
    forced xs = forceElements xs `seq` xs

solve :: [[V]] -> Answer
solve rows = min a2 a5
  where
    a2 = findAnswer (Factor 2) rows
    a5 = findAnswer (Factor 5) rows

findAnswer :: Factor -> [[V]] -> Answer
findAnswer p (row:rows) = last $ foldl' (nextRow p) (firstRow p row) rows

firstRow :: Factor -> [V] -> [Answer]
firstRow p (first:rest) = scanl step initial rest
  where
    initial = Answer (toWeight p first) ""
    step a v = moveRight a (toWeight p v)

nextRow :: Factor -> [Answer] -> [V] -> [Answer]
nextRow p (firstUp:restUp) (first:rest) = scanl' step initial (zip restUp rest)
  where
    initial = moveDown firstUp $ toWeight p first
    step left (up, v)  = let w = toWeight p v
     in min (moveRight left w) (moveDown up w)

moveRight :: Answer -> Weight -> Answer
moveRight (Answer w1 p) w2 = Answer (w1 <> w2) ('R':p)

moveDown :: Answer -> Weight -> Answer
moveDown (Answer w1 p) w2 = Answer (w1 <> w2) ('D':p)

toWeight :: Factor -> V -> Weight
toWeight _ 0 = Zeroed
toWeight p k = Amount (count p k)

unWeight :: Weight -> V
unWeight Zeroed = 1
unWeight (Amount a) = unCounted a

count :: Factor -> V -> Counted
count (Factor d) value = countD0 value 0
  where
    countD0 value acc = let (q, r) = quotRem value d
     in if r == 0 then countD0 q (acc + 1) else Counted acc

forceElements :: [a] -> ()
forceElements = foldr seq ()

newtype Size = Size { unSize :: V } deriving (Show)
newtype Factor = Factor V
newtype Counted = Counted { unCounted :: V }
 deriving (Show, Eq, Ord)
 deriving Semigroup via (Sum V)

data Weight = Zeroed | Amount !Counted
  deriving (Show, Eq)

instance Ord Weight where
  compare a b = compare (unWeight a) (unWeight b)

instance Semigroup Weight where
  Zeroed <> _ = Zeroed
  _ <> Zeroed = Zeroed
  (Amount a) <> (Amount b) = Amount (a <> b)

data Answer = Answer { weight :: !Weight
                     , path :: String
                     } deriving (Show)

instance Eq Answer where
  a == b = weight a == weight b

instance Ord Answer where
  compare = comparing weight

{-# LANGUAGE DerivingVia #-}
module Main where

import Data.List (foldl')

import qualified Data.Array.IArray as I
import qualified Data.Array as A
import qualified Data.ByteString.Char8 as B

import Control.Monad (forM_, replicateM)
import Data.Functor ((<&>))
import Data.Semigroup (Sum(..))
import Data.Ord (comparing)
import Data.Maybe (fromJust)
import Data.Word

type V = Int

main :: IO ()
main = do
  Answer w p <- solve <$> readInput
  print (unWeight w)
  putStrLn (reverse p)

readInput :: IO [[V]]
readInput = do
    n <- readLn
    replicateM n $ B.getLine <&> forced . readLine
  where
    readLine = map (fst . fromJust . B.readInt) . B.words

solve :: [[V]] -> Answer
solve rows = min a2 a5
  where
    a2 = findAnswer (Factor 2) rows
    a5 = findAnswer (Factor 5) rows

findAnswer :: Factor -> [[V]] -> Answer
findAnswer p (row:rows) = last $ foldl' (nextRow p) (firstRow p row) rows

firstRow :: Factor -> [V] -> [Answer]
firstRow p (first:rest) = scanl' step initial rest
  where
    initial = Answer (toWeight p first) ""
    step a v = moveRight a (toWeight p v)

nextRow :: Factor -> [Answer] -> [V] -> [Answer]
nextRow p (firstUp:restUp) (first:rest) = scanl' step initial (zip restUp rest)
  where
    initial = moveDown firstUp $ toWeight p first
    step left (up, v)  = let w = toWeight p v
     in min (moveRight left w) (moveDown up w)

moveRight :: Answer -> Weight -> Answer
moveRight (Answer w1 p) w2 = Answer (w1 <> w2) ('R':p)

moveDown :: Answer -> Weight -> Answer
moveDown (Answer w1 p) w2 = Answer (w1 <> w2) ('D':p)

toWeight :: Factor -> V -> Weight
toWeight _ 0 = Zeroed
toWeight p k = Amount (count p k)

unWeight :: Weight -> V
unWeight Zeroed = 1
unWeight (Amount a) = unCounted a

count :: Factor -> V -> Counted
count (Factor d) value = countD0 value 0
  where
    countD0 value acc = let (q, r) = quotRem value d
     in if r == 0 then countD0 q (acc + 1) else Counted acc

forceElements :: [a] -> ()
forceElements = foldr seq ()

forced :: [a] -> [a]
forced xs = forceElements xs `seq` xs

scanl' :: (b -> a -> b) -> b -> [a] -> [b]
scanl' f q [] = q `seq` [q]
scanl' f q (x:xs) = q `seq` rest `seq` q:rest
  where
    rest = scanl' f (f q x) xs

newtype Size = Size { unSize :: V } deriving (Show)
newtype Factor = Factor V
newtype Counted = Counted { unCounted :: V }
 deriving (Show, Eq, Ord)
 deriving Semigroup via (Sum V)

data Weight = Zeroed | Amount !Counted
  deriving (Show, Eq)

instance Ord Weight where
  compare a b = compare (unWeight a) (unWeight b)

instance Semigroup Weight where
  Zeroed <> _ = Zeroed
  _ <> Zeroed = Zeroed
  (Amount a) <> (Amount b) = Amount (a <> b)

data Answer = Answer { weight :: !Weight
                     , path :: String
                     } deriving (Show)

instance Eq Answer where
  a == b = weight a == weight b

instance Ord Answer where
  compare = comparing weight

{-# LANGUAGE DerivingVia #-}
module Main where

import Data.List (foldl')

import qualified Data.Array.IArray as I
import qualified Data.Array as A
import qualified Data.ByteString.Char8 as B

import Control.Monad (forM_, replicateM)
import Data.Functor ((<&>))
import Data.Semigroup (Sum(..))
import Data.Ord (comparing)
import Data.Maybe (fromJust)
import Data.Word

type V = Int

main :: IO ()
main = do
  Answer w p <- solve <$> readInput
  print (unWeight w)
  putStrLn (reverse p)

readInput :: IO [[V]]
readInput = do
    n <- readLn
    rows <- replicateM n $ B.getLine <&> readLine
    return (forced rows)
  where
    readLine = map' (fst . fromJust . B.readInt) . B.words

solve :: [[V]] -> Answer
solve rows = min a2 a5
  where
    a2 = findAnswer (Factor 2) rows
    a5 = findAnswer (Factor 5) rows

findAnswer :: Factor -> [[V]] -> Answer
findAnswer p (row:rows) = last $ foldl' (nextRow p) (firstRow p row) rows

firstRow :: Factor -> [V] -> [Answer]
firstRow p (first:rest) = scanl' step initial rest
  where
    initial = Answer (toWeight p first) ""
    step a v = moveRight a (toWeight p v)

nextRow :: Factor -> [Answer] -> [V] -> [Answer]
nextRow p (firstUp:restUp) (first:rest) = scanl' step initial (zip restUp rest)
  where
    initial = moveDown firstUp $ toWeight p first
    step left (up, v)  = let w = toWeight p v
     in min (moveRight left w) (moveDown up w)

moveRight :: Answer -> Weight -> Answer
moveRight (Answer w1 p) w2 = Answer (w1 <> w2) ('R':p)

moveDown :: Answer -> Weight -> Answer
moveDown (Answer w1 p) w2 = Answer (w1 <> w2) ('D':p)

toWeight :: Factor -> V -> Weight
toWeight _ 0 = Zeroed
toWeight p k = Amount (count p k)

unWeight :: Weight -> V
unWeight Zeroed = 1
unWeight (Amount a) = unCounted a

count :: Factor -> V -> Counted
count (Factor d) value = countD0 value 0
  where
    countD0 value acc = let (q, r) = quotRem value d
     in if r == 0 then countD0 q (acc + 1) else Counted acc

forceElements :: [a] -> ()
forceElements = foldr seq ()

forced :: [a] -> [a]
forced xs = forceElements xs `seq` xs

scanl' :: (b -> a -> b) -> b -> [a] -> [b]
scanl' f q [] = q `seq` [q]
scanl' f q (x:xs) = q `seq` rest `seq` q:rest
  where
    rest = scanl' f (f q x) xs

map' :: (a -> b) -> [a] -> [b]
map' f [] = []
map' f (x:xs) = y `seq` y:map' f xs
  where y = f x

newtype Size = Size { unSize :: V } deriving (Show)
newtype Factor = Factor V
newtype Counted = Counted { unCounted :: V }
 deriving (Show, Eq, Ord)
 deriving Semigroup via (Sum V)

data Weight = Zeroed | Amount !Counted
  deriving (Show, Eq)

instance Ord Weight where
  compare a b = compare (unWeight a) (unWeight b)

instance Semigroup Weight where
  Zeroed <> _ = Zeroed
  _ <> Zeroed = Zeroed
  (Amount a) <> (Amount b) = Amount (a <> b)

data Answer = Answer { weight :: !Weight
                     , path :: String
                     } deriving (Show)

instance Eq Answer where
  a == b = weight a == weight b

instance Ord Answer where
  compare = comparing weight

{-# LANGUAGE DerivingVia #-}
module Main where

import Data.List (foldl')

import qualified Data.Array.IArray as I
import qualified Data.Array as A
import qualified Data.ByteString.Char8 as B

import Control.Monad (forM_, replicateM)
import Data.Functor ((<&>))
import Data.Semigroup (Sum(..))
import Data.Ord (comparing)
import Data.Maybe (fromJust)
import Data.Word
import GHC.List (scanl')

type V = Int

main :: IO ()
main = do
  Answer w p <- solve <$> readInput
  print (unWeight w)
  putStrLn (reverse p)

readInput :: IO [[V]]
readInput = do
    n <- readLn
    rows <- replicateM n $ B.getLine <&> forced . readLine
    return (forced rows)
  where
    readLine = map (fst . fromJust . B.readInt) . B.words

solve :: [[V]] -> Answer
solve rows = min a2 a5
  where
    a2 = findAnswer (Factor 2) rows
    a5 = findAnswer (Factor 5) rows

findAnswer :: Factor -> [[V]] -> Answer
findAnswer p (row:rows) = last $ foldl' (nextRow p) (firstRow p row) rows

firstRow :: Factor -> [V] -> [Answer]
firstRow p (first:rest) = forced $ scanl step initial rest
  where
    initial = Answer (toWeight p first) ""
    step a v = moveRight a (toWeight p v)

nextRow :: Factor -> [Answer] -> [V] -> [Answer]
nextRow p (firstUp:restUp) (first:rest) = forced $ scanl' step initial (zip restUp rest)
  where
    initial = moveDown firstUp $ toWeight p first
    step left (up, v)  = let w = toWeight p v
     in min (moveRight left w) (moveDown up w)

moveRight :: Answer -> Weight -> Answer
moveRight (Answer w1 p) w2 = Answer (w1 <> w2) ('R':p)

moveDown :: Answer -> Weight -> Answer
moveDown (Answer w1 p) w2 = Answer (w1 <> w2) ('D':p)

toWeight :: Factor -> V -> Weight
toWeight _ 0 = Zeroed
toWeight p k = Amount (count p k)

unWeight :: Weight -> V
unWeight Zeroed = 1
unWeight (Amount a) = unCounted a

count :: Factor -> V -> Counted
count (Factor d) value = countD0 value 0
  where
    countD0 value acc = let (q, r) = quotRem value d
     in if r == 0 then countD0 q (acc + 1) else Counted acc

forceElements :: [a] -> ()
forceElements = foldr seq ()

forced :: [a] -> [a]
forced xs = forceElements xs `seq` xs

newtype Size = Size { unSize :: V } deriving (Show)
newtype Factor = Factor V
newtype Counted = Counted { unCounted :: V }
 deriving (Show, Eq, Ord)
 deriving Semigroup via (Sum V)

data Weight = Zeroed | Amount !Counted
  deriving (Show, Eq)

instance Ord Weight where
  compare a b = compare (unWeight a) (unWeight b)

instance Semigroup Weight where
  Zeroed <> _ = Zeroed
  _ <> Zeroed = Zeroed
  (Amount a) <> (Amount b) = Amount (a <> b)

data Answer = Answer { weight :: !Weight
                     , path :: String
                     } deriving (Show)

instance Eq Answer where
  a == b = weight a == weight b

instance Ord Answer where
  compare = comparing weight

{-# LANGUAGE DerivingVia #-}
module Main where

import Data.List (foldl')

import qualified Data.Array.IArray as I
import qualified Data.Array as A
import qualified Data.ByteString.Char8 as B

import Control.Monad (forM_, replicateM)
import Data.Functor ((<&>))
import Data.Semigroup (Sum(..))
import Data.Ord (comparing)
import Data.Maybe (fromJust)
import Data.Word

type V = Int

main :: IO ()
main = do
  Answer w p <- solve <$> readInput
  print (unWeight w)
  putStrLn (reverse p)

readInput :: IO [[V]]
readInput = do
    n <- readLn
    replicateM n $ B.getLine <&> forced . readLine
  where
    readLine = map (fst . fromJust . B.readInt) . B.words

solve :: [[V]] -> Answer
solve rows = min a2 a5
  where
    a2 = findAnswer (Factor 2) rows
    a5 = findAnswer (Factor 5) rows

findAnswer :: Factor -> [[V]] -> Answer
findAnswer p (row:rows) = last $ foldl' (nextRow p) (firstRow p row) rows

firstRow :: Factor -> [V] -> [Answer]
firstRow p (first:rest) = scanl' step initial rest
  where
    initial = Answer (toWeight p first) ""
    step a v = moveRight a (toWeight p v)

nextRow :: Factor -> [Answer] -> [V] -> [Answer]
nextRow p (firstUp:restUp) (first:rest) = scanl' step initial (zip restUp rest)
  where
    initial = moveDown firstUp $ toWeight p first
    step left (up, v)  = let w = toWeight p v
     in min (moveRight left w) (moveDown up w)

moveRight :: Answer -> Weight -> Answer
moveRight (Answer w1 p) w2 = Answer (w1 <> w2) ('R':p)

moveDown :: Answer -> Weight -> Answer
moveDown (Answer w1 p) w2 = Answer (w1 <> w2) ('D':p)

toWeight :: Factor -> V -> Weight
toWeight _ 0 = Zeroed
toWeight p k = Amount (count p k)

unWeight :: Weight -> V
unWeight Zeroed = 1
unWeight (Amount a) = unCounted a

count :: Factor -> V -> Counted
count (Factor d) value = countD0 value 0
  where
    countD0 value acc = let (q, r) = quotRem value d
     in if r == 0 then countD0 q (acc + 1) else Counted acc

forceElements :: [a] -> ()
forceElements = foldr seq ()

forced :: [a] -> [a]
forced xs = forceElements xs `seq` xs

scanl' :: (b -> a -> b) -> b -> [a] -> [b]
scanl' f q ls = forced (scanl f q ls)

newtype Size = Size { unSize :: V } deriving (Show)
newtype Factor = Factor V
newtype Counted = Counted { unCounted :: V }
 deriving (Show, Eq, Ord)
 deriving Semigroup via (Sum V)

data Weight = Zeroed | Amount !Counted
  deriving (Show, Eq)

instance Ord Weight where
  compare a b = compare (unWeight a) (unWeight b)

instance Semigroup Weight where
  Zeroed <> _ = Zeroed
  _ <> Zeroed = Zeroed
  (Amount a) <> (Amount b) = Amount (a <> b)

data Answer = Answer { weight :: !Weight
                     , path :: String
                     } deriving (Show)

instance Eq Answer where
  a == b = weight a == weight b

instance Ord Answer where
  compare = comparing weight

{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE BangPatterns #-}
module Main where

import Data.List (foldl')

import qualified Data.Array.IArray as I
import qualified Data.Array as A
import qualified Data.ByteString.Char8 as B

import Data.Array.Unboxed (UArray)

import Control.Monad (forM_, replicateM)
import Data.Functor ((<&>))
import Data.Semigroup (Sum(..))
import Data.Ord (comparing)
import Data.Maybe (fromJust)
import Data.Word
import GHC.List (scanl')

type V = Int
type R = UArray Int V

badInput :: [R]
badInput = replicate 1000 $ I.listArray (1, 1000) (replicate 1000 646642320)

main :: IO ()
main = do
  Answer w p <- solve <$> readInput
  print (unWeight w)
  putStrLn (reverse p)

readInput :: IO [R]
readInput = do
    n <- readLn
    replicateM n $ B.getLine <&> I.listArray (1, n) . readLine
  where
    readLine = map (fst . fromJust . B.readInt) . B.words

solve :: [R] -> Answer
solve rows = min a2 a5
  where
    a2 = findAnswer (Factor 2) rows
    a5 = findAnswer (Factor 5) rows

findAnswer :: Factor -> [R] -> Answer
findAnswer p (row:rows) = last $ foldl' (nextRow p) (firstRow p row) rows

firstRow :: Factor -> R -> [Answer]
firstRow p row = scanl step initial rest
  where
    (first:rest) = I.elems row
    initial = Answer (toWeight p first) ""
    step a v = moveRight a (toWeight p v)

nextRow :: Factor -> [Answer] -> R -> [Answer]
nextRow p (firstUp:restUp) row = scanl' step initial (zip restUp rest)
  where
    (first:rest) = I.elems row
    initial = moveDown firstUp $ toWeight p first
    step !left (up, v)  = let w = toWeight p v
     in min (moveRight left w) (moveDown up w)

moveRight :: Answer -> Weight -> Answer
moveRight (Answer w1 p) w2 = Answer (w1 <> w2) ('R':p)

moveDown :: Answer -> Weight -> Answer
moveDown (Answer w1 p) w2 = Answer (w1 <> w2) ('D':p)

toWeight :: Factor -> V -> Weight
toWeight _ 0 = Zeroed
toWeight p k = Amount (count p k)

unWeight :: Weight -> V
unWeight Zeroed = 1
unWeight (Amount a) = unCounted a

count :: Factor -> V -> Counted
count (Factor d) value = countD0 value 0
  where
    countD0 value acc = let (q, r) = quotRem value d
     in if r == 0 then countD0 q (acc + 1) else Counted acc

newtype Size = Size { unSize :: V } deriving (Show)
newtype Factor = Factor V
newtype Counted = Counted { unCounted :: V }
 deriving (Show, Eq, Ord)
 deriving Semigroup via (Sum V)

data Weight = Zeroed | Amount !Counted
  deriving (Show, Eq)

instance Ord Weight where
  compare a b = compare (unWeight a) (unWeight b)

instance Semigroup Weight where
  Zeroed <> _ = Zeroed
  _ <> Zeroed = Zeroed
  (Amount a) <> (Amount b) = Amount (a <> b)

data Answer = Answer { weight :: !Weight
                     , path :: String
                     } deriving (Show)

instance Eq Answer where
  a == b = weight a == weight b

instance Ord Answer where
  compare = comparing weight

{-# LANGUAGE DerivingVia #-}
module Main where

import Data.List (foldl')

import qualified Data.Array.IArray as I
import qualified Data.Array as A
import qualified Data.ByteString.Char8 as B

import Control.Monad (forM_, replicateM)
import Data.Functor ((<&>))
import Data.Semigroup (Sum(..))
import Data.Ord (comparing)
import Data.Maybe (fromJust)
import Data.Word
import GHC.List (scanl')

type V = Int

main :: IO ()
main = do
  Answer w p <- solve <$> readInput
  print (unWeight w)
  putStrLn (reverse p)

readInput :: IO [[V]]
readInput = do
    n <- readLn
    rows <- replicateM n $ B.getLine <&> forced . readLine
    return (forced rows)
  where
    readLine = map (fst . fromJust . B.readInt) . B.words
    forced xs = forceElements xs `seq` xs

solve :: [[V]] -> Answer
solve rows = min a2 a5
  where
    a2 = findAnswer (Factor 2) rows
    a5 = findAnswer (Factor 5) rows

findAnswer :: Factor -> [[V]] -> Answer
findAnswer p (row:rows) = last $ foldl' (nextRow p) (firstRow p row) rows

firstRow :: Factor -> [V] -> [Answer]
firstRow p (first:rest) = scanl step initial rest
  where
    initial = Answer (toWeight p first) ""
    step a v = moveRight a (toWeight p v)

nextRow :: Factor -> [Answer] -> [V] -> [Answer]
nextRow p (firstUp:restUp) (first:rest) = scanl' step initial (zip restUp rest)
  where
    initial = moveDown firstUp $ toWeight p first
    step left (up, v)  = let w = toWeight p v
     in min (moveRight left w) (moveDown up w)

moveRight :: Answer -> Weight -> Answer
moveRight (Answer w1 p) w2 = Answer (w1 <> w2) ('R':p)

moveDown :: Answer -> Weight -> Answer
moveDown (Answer w1 p) w2 = Answer (w1 <> w2) ('D':p)

toWeight :: Factor -> V -> Weight
toWeight _ 0 = Zeroed
toWeight p k = Amount (count p k)

unWeight :: Weight -> V
unWeight Zeroed = 1
unWeight (Amount a) = unCounted a

count :: Factor -> V -> Counted
count (Factor d) value = countD0 value 0
  where
    countD0 value acc = let (q, r) = quotRem value d
     in if r == 0 then countD0 q (acc + 1) else Counted acc

forceElements :: [a] -> ()
forceElements = foldr seq ()

newtype Size = Size { unSize :: V } deriving (Show)
newtype Factor = Factor V
newtype Counted = Counted { unCounted :: V }
 deriving (Show, Eq, Ord)
 deriving Semigroup via (Sum V)

data Weight = Zeroed | Amount !Counted
  deriving (Show, Eq)

instance Ord Weight where
  compare a b = compare (unWeight a) (unWeight b)

instance Semigroup Weight where
  Zeroed <> _ = Zeroed
  _ <> Zeroed = Zeroed
  (Amount a) <> (Amount b) = Amount (a <> b)

data Answer = Answer { weight :: !Weight
                     , path :: String
                     } deriving (Show)

instance Eq Answer where
  a == b = weight a == weight b

instance Ord Answer where
  compare = comparing weight

{-# LANGUAGE DerivingVia #-}
module Main where

import Data.List (foldl')

import qualified Data.Array.IArray as I
import qualified Data.Array as A
import qualified Data.ByteString.Char8 as B

import Control.Monad (forM_, replicateM)
import Data.Functor ((<&>))
import Data.Semigroup (Sum(..))
import Data.Ord (comparing)
import Data.Maybe (fromJust)
import Data.Word

type V = Int

main :: IO ()
main = do
  Answer w p <- solve <$> readInput
  print (unWeight w)
  putStrLn (reverse p)

readInput :: IO [[V]]
readInput = do
    n <- readLn
    replicateM n $ B.getLine <&> readLine
  where
    readLine = map' (fst . fromJust . B.readInt) . B.words

solve :: [[V]] -> Answer
solve rows = min a2 a5
  where
    a2 = findAnswer (Factor 2) rows
    a5 = findAnswer (Factor 5) rows

findAnswer :: Factor -> [[V]] -> Answer
findAnswer p (row:rows) = last $ foldl' (nextRow p) (firstRow p row) rows

firstRow :: Factor -> [V] -> [Answer]
firstRow p (first:rest) = scanl' step initial rest
  where
    initial = Answer (toWeight p first) ""
    step a v = moveRight a (toWeight p v)

nextRow :: Factor -> [Answer] -> [V] -> [Answer]
nextRow p (firstUp:restUp) (first:rest) = scanl' step initial (zip restUp rest)
  where
    initial = moveDown firstUp $ toWeight p first
    step left (up, v)  = let w = toWeight p v
     in min (moveRight left w) (moveDown up w)

moveRight :: Answer -> Weight -> Answer
moveRight (Answer w1 p) w2 = Answer (w1 <> w2) ('R':p)

moveDown :: Answer -> Weight -> Answer
moveDown (Answer w1 p) w2 = Answer (w1 <> w2) ('D':p)

toWeight :: Factor -> V -> Weight
toWeight _ 0 = Zeroed
toWeight p k = Amount (count p k)

unWeight :: Weight -> V
unWeight Zeroed = 1
unWeight (Amount a) = unCounted a

count :: Factor -> V -> Counted
count (Factor d) value = countD0 value 0
  where
    countD0 value acc = let (q, r) = quotRem value d
     in if r == 0 then countD0 q (acc + 1) else Counted acc

forceElements :: [a] -> ()
forceElements = foldr seq ()

forced :: [a] -> [a]
forced xs = forceElements xs `seq` xs

scanl' :: (b -> a -> b) -> b -> [a] -> [b]
scanl' f q [] = q `seq` [q]
scanl' f q (x:xs) = q `seq` rest `seq` q:rest
  where
    rest = scanl' f (f q x) xs

map' :: (a -> b) -> [a] -> [b]
map' f [] = []
map' f (x:xs) = y `seq` y:map' f xs
  where y = f x

newtype Size = Size { unSize :: V } deriving (Show)
newtype Factor = Factor V
newtype Counted = Counted { unCounted :: V }
 deriving (Show, Eq, Ord)
 deriving Semigroup via (Sum V)

data Weight = Zeroed | Amount !Counted
  deriving (Show, Eq)

instance Ord Weight where
  compare a b = compare (unWeight a) (unWeight b)

instance Semigroup Weight where
  Zeroed <> _ = Zeroed
  _ <> Zeroed = Zeroed
  (Amount a) <> (Amount b) = Amount (a <> b)

data Answer = Answer { weight :: !Weight
                     , path :: String
                     } deriving (Show)

instance Eq Answer where
  a == b = weight a == weight b

instance Ord Answer where
  compare = comparing weight

{-# LANGUAGE DerivingVia #-}
module Main where

import Data.List (foldl')

import qualified Data.Array.IArray as I
import qualified Data.Array as A
import qualified Data.ByteString.Char8 as B

import Control.Monad (forM_, replicateM)
import Data.Functor ((<&>))
import Data.Semigroup (Sum(..))
import Data.Ord (comparing)
import Data.Maybe (fromJust)
import Data.Word

type V = Int

main :: IO ()
main = do
  Answer w p <- solve <$> readInput
  print (unWeight w)
  putStrLn (reverse p)

readInput :: IO [[V]]
readInput = do
    n <- readLn
    replicateM n $ B.getLine <&> readLine
  where
    readLine = map (fst . fromJust . B.readInt) . B.words

solve :: [[V]] -> Answer
solve rows = min a2 a5
  where
    a2 = findAnswer (Factor 2) rows
    a5 = findAnswer (Factor 5) rows

findAnswer :: Factor -> [[V]] -> Answer
findAnswer p (row:rows) = last $ foldl' (nextRow p) (firstRow p row) rows

firstRow :: Factor -> [V] -> [Answer]
firstRow p (first:rest) = scanl' step initial rest
  where
    initial = Answer (toWeight p first) ""
    step a v = moveRight a (toWeight p v)

nextRow :: Factor -> [Answer] -> [V] -> [Answer]
nextRow p (firstUp:restUp) (first:rest) = scanl' step initial (zip restUp rest)
  where
    initial = moveDown firstUp $ toWeight p first
    step left (up, v)  = let w = toWeight p v
     in min (moveRight left w) (moveDown up w)

moveRight :: Answer -> Weight -> Answer
moveRight (Answer w1 p) w2 = Answer (w1 <> w2) ('R':p)

moveDown :: Answer -> Weight -> Answer
moveDown (Answer w1 p) w2 = Answer (w1 <> w2) ('D':p)

toWeight :: Factor -> V -> Weight
toWeight _ 0 = Zeroed
toWeight p k = Amount (count p k)

unWeight :: Weight -> V
unWeight Zeroed = 1
unWeight (Amount a) = unCounted a

count :: Factor -> V -> Counted
count (Factor d) value = countD0 value 0
  where
    countD0 value acc = let (q, r) = quotRem value d
     in if r == 0 then countD0 q (acc + 1) else Counted acc

forceElements :: [a] -> ()
forceElements = foldr seq ()

forced :: [a] -> [a]
forced xs = forceElements xs `seq` xs

scanl' :: (b -> a -> b) -> b -> [a] -> [b]
scanl' f q ls = forced (scanl f q ls)

newtype Size = Size { unSize :: V } deriving (Show)
newtype Factor = Factor V
newtype Counted = Counted { unCounted :: V }
 deriving (Show, Eq, Ord)
 deriving Semigroup via (Sum V)

data Weight = Zeroed | Amount !Counted
  deriving (Show, Eq)

instance Ord Weight where
  compare a b = compare (unWeight a) (unWeight b)

instance Semigroup Weight where
  Zeroed <> _ = Zeroed
  _ <> Zeroed = Zeroed
  (Amount a) <> (Amount b) = Amount (a <> b)

data Answer = Answer { weight :: !Weight
                     , path :: String
                     } deriving (Show)

instance Eq Answer where
  a == b = weight a == weight b

instance Ord Answer where
  compare = comparing weight

{-# LANGUAGE DerivingVia #-}
module Main where

import Data.List (foldl')

import qualified Data.Array.IArray as I
import qualified Data.Array as A
import qualified Data.ByteString.Char8 as B

import Control.Monad (forM_, replicateM)
import Data.Functor ((<&>))
import Data.Semigroup (Sum(..))
import Data.Ord (comparing)
import Data.Maybe (fromJust)
import Data.Word

type V = Int

main :: IO ()
main = do
  Answer w p <- solve <$> readInput
  print (unWeight w)
  putStrLn (reverse p)

readInput :: IO [[V]]
readInput = do
    n <- readLn
    rows <- replicateM n $ B.getLine <&> forced . readLine
    return $ forced rows
  where
    readLine = map (fst . fromJust . B.readInt) . B.words

solve :: [[V]] -> Answer
solve rows = min a2 a5
  where
    a2 = findAnswer (Factor 2) rows
    a5 = findAnswer (Factor 5) rows

findAnswer :: Factor -> [[V]] -> Answer
findAnswer p (row:rows) = last $ foldl' (nextRow p) (firstRow p row) rows

firstRow :: Factor -> [V] -> [Answer]
firstRow p (first:rest) = scanl' step initial rest
  where
    initial = Answer (toWeight p first) ""
    step a v = moveRight a (toWeight p v)

nextRow :: Factor -> [Answer] -> [V] -> [Answer]
nextRow p (firstUp:restUp) (first:rest) = scanl' step initial (zip restUp rest)
  where
    initial = moveDown firstUp $ toWeight p first
    step left (up, v)  = let w = toWeight p v
     in min (moveRight left w) (moveDown up w)

moveRight :: Answer -> Weight -> Answer
moveRight (Answer w1 p) w2 = Answer (w1 <> w2) ('R':p)

moveDown :: Answer -> Weight -> Answer
moveDown (Answer w1 p) w2 = Answer (w1 <> w2) ('D':p)

toWeight :: Factor -> V -> Weight
toWeight _ 0 = Zeroed
toWeight p k = Amount (count p k)

unWeight :: Weight -> V
unWeight Zeroed = 1
unWeight (Amount a) = unCounted a

count :: Factor -> V -> Counted
count (Factor d) value = countD0 value 0
  where
    countD0 value acc = let (q, r) = quotRem value d
     in if r == 0 then countD0 q (acc + 1) else Counted acc

forceElements :: [a] -> ()
forceElements = foldr seq ()

forced :: [a] -> [a]
forced xs = forceElements xs `seq` xs

scanl' :: (b -> a -> b) -> b -> [a] -> [b]
scanl' f q ls = forced (scanl f q ls)

newtype Size = Size { unSize :: V } deriving (Show)
newtype Factor = Factor V
newtype Counted = Counted { unCounted :: V }
 deriving (Show, Eq, Ord)
 deriving Semigroup via (Sum V)

data Weight = Zeroed | Amount !Counted
  deriving (Show, Eq)

instance Ord Weight where
  compare a b = compare (unWeight a) (unWeight b)

instance Semigroup Weight where
  Zeroed <> _ = Zeroed
  _ <> Zeroed = Zeroed
  (Amount a) <> (Amount b) = Amount (a <> b)

data Answer = Answer { weight :: !Weight
                     , path :: String
                     } deriving (Show)

instance Eq Answer where
  a == b = weight a == weight b

instance Ord Answer where
  compare = comparing weight

{-# LANGUAGE DerivingVia #-}
module Main where

import Data.List (foldl')

import qualified Data.Array.IArray as I
import qualified Data.Array as A
import qualified Data.ByteString.Char8 as B

import Control.Monad (forM_, replicateM)
import Data.Functor ((<&>))
import Data.Semigroup (Sum(..))
import Data.Ord (comparing)
import Data.Maybe (fromJust)
import Data.Word

type V = Int

main :: IO ()
main = do
  Answer w p <- solve <$> readInput
  print (unWeight w)
  putStrLn (reverse p)

readInput :: IO [[V]]
readInput = do
    n <- readLn
    replicateM n $ B.getLine <&> readLine
  where
    readLine = map (fst . fromJust . B.readInt) . B.words

solve :: [[V]] -> Answer
solve rows = min a2 a5
  where
    a2 = findAnswer (Factor 2) rows
    a5 = findAnswer (Factor 5) rows

findAnswer :: Factor -> [[V]] -> Answer
findAnswer p (row:rows) = last $ foldl' (nextRow p) (firstRow p row) rows

firstRow :: Factor -> [V] -> [Answer]
firstRow p (first:rest) = scanl' step initial rest
  where
    initial = Answer (toWeight p first) ""
    step a v = moveRight a (toWeight p v)

nextRow :: Factor -> [Answer] -> [V] -> [Answer]
nextRow p (firstUp:restUp) (first:rest) = scanl' step initial (zip restUp rest)
  where
    initial = moveDown firstUp $ toWeight p first
    step left (up, v)  = let w = toWeight p v
     in min (moveRight left w) (moveDown up w)

moveRight :: Answer -> Weight -> Answer
moveRight (Answer w1 p) w2 = Answer (w1 <> w2) ('R':p)

moveDown :: Answer -> Weight -> Answer
moveDown (Answer w1 p) w2 = Answer (w1 <> w2) ('D':p)

toWeight :: Factor -> V -> Weight
toWeight _ 0 = Zeroed
toWeight p k = Amount (count p k)

unWeight :: Weight -> V
unWeight Zeroed = 1
unWeight (Amount a) = unCounted a

count :: Factor -> V -> Counted
count (Factor d) value = countD0 value 0
  where
    countD0 value acc = let (q, r) = quotRem value d
     in if r == 0 then countD0 q (acc + 1) else Counted acc

forceElements :: [a] -> ()
forceElements = foldl' (flip seq) ()

forced :: [a] -> [a]
forced xs = forceElements xs `seq` xs

scanl' :: (b -> a -> b) -> b -> [a] -> [b]
scanl' f q = forced . scanl f q

newtype Size = Size { unSize :: V } deriving (Show)
newtype Factor = Factor V
newtype Counted = Counted { unCounted :: V }
 deriving (Show, Eq, Ord)
 deriving Semigroup via (Sum V)

data Weight = Zeroed | Amount !Counted
  deriving (Show, Eq)

instance Ord Weight where
  compare a b = compare (unWeight a) (unWeight b)

instance Semigroup Weight where
  Zeroed <> _ = Zeroed
  _ <> Zeroed = Zeroed
  (Amount a) <> (Amount b) = Amount (a <> b)

data Answer = Answer { weight :: !Weight
                     , path :: String
                     } deriving (Show)

instance Eq Answer where
  a == b = weight a == weight b

instance Ord Answer where
  compare = comparing weight

{-# LANGUAGE DerivingVia #-}
module Main where

import Data.List (foldl')

import qualified Data.Array.IArray as I
import qualified Data.Array as A
import qualified Data.ByteString.Char8 as B

import Control.Monad (forM_, replicateM)
import Data.Functor ((<&>))
import Data.Semigroup (Sum(..))
import Data.Ord (comparing)
import Data.Maybe (fromJust)
import Data.Word

type V = Int

main :: IO ()
main = do
  Answer w p <- solve <$> readInput
  print (unWeight w)
  putStrLn (reverse p)

readInput :: IO [[V]]
readInput = do
    n <- readLn
    rows <- replicateM n $ B.getLine <&> forced . readLine
    return (forced rows)
  where
    readLine = map (fst . fromJust . B.readInt) . B.words

solve :: [[V]] -> Answer
solve rows = min a2 a5
  where
    a2 = findAnswer (Factor 2) rows
    a5 = findAnswer (Factor 5) rows

findAnswer :: Factor -> [[V]] -> Answer
findAnswer p (row:rows) = last $ foldl' (nextRow p) (firstRow p row) rows

firstRow :: Factor -> [V] -> [Answer]
firstRow p (first:rest) = scanl' step initial rest
  where
    initial = Answer (toWeight p first) ""
    step a v = moveRight a (toWeight p v)

nextRow :: Factor -> [Answer] -> [V] -> [Answer]
nextRow p (firstUp:restUp) (first:rest) = scanl' step initial (zip restUp rest)
  where
    initial = moveDown firstUp $ toWeight p first
    step left (up, v)  = let w = toWeight p v
     in min (moveRight left w) (moveDown up w)

moveRight :: Answer -> Weight -> Answer
moveRight (Answer w1 p) w2 = Answer (w1 <> w2) ('R':p)

moveDown :: Answer -> Weight -> Answer
moveDown (Answer w1 p) w2 = Answer (w1 <> w2) ('D':p)

toWeight :: Factor -> V -> Weight
toWeight _ 0 = Zeroed
toWeight p k = Amount (count p k)

unWeight :: Weight -> V
unWeight Zeroed = 1
unWeight (Amount a) = unCounted a

count :: Factor -> V -> Counted
count (Factor d) value = countD0 value 0
  where
    countD0 value acc = let (q, r) = quotRem value d
     in if r == 0 then countD0 q (acc + 1) else Counted acc

forceElements :: [a] -> ()
forceElements = foldr seq ()

forced :: [a] -> [a]
forced xs = forceElements xs `seq` xs

scanl' :: (b -> a -> b) -> b -> [a] -> [b]
scanl' f q [] = q `seq` [q]
scanl' f q (x:xs) = q `seq` rest `seq` q:rest
  where
    rest = scanl' f (f q x) xs

newtype Size = Size { unSize :: V } deriving (Show)
newtype Factor = Factor V
newtype Counted = Counted { unCounted :: V }
 deriving (Show, Eq, Ord)
 deriving Semigroup via (Sum V)

data Weight = Zeroed | Amount !Counted
  deriving (Show, Eq)

instance Ord Weight where
  compare a b = compare (unWeight a) (unWeight b)

instance Semigroup Weight where
  Zeroed <> _ = Zeroed
  _ <> Zeroed = Zeroed
  (Amount a) <> (Amount b) = Amount (a <> b)

data Answer = Answer { weight :: !Weight
                     , path :: String
                     } deriving (Show)

instance Eq Answer where
  a == b = weight a == weight b

instance Ord Answer where
  compare = comparing weight

module Main where

import qualified Data.Array.IArray as I
import qualified Data.Array as A
import Data.Array.Unboxed
import Data.List (foldl')
import qualified Data.ByteString.Char8 as B

scanl' :: (a -> b -> a) -> a -> [b] -> [a]
scanl' _ z  []    = [z]
scanl' f z (x:xs) = let u = f z x
                        ys = z:scanl' f u xs
                    in u `seq` ys `seq` ys

powerOf :: Int -> Int -> Int
powerOf _ 0 = error "powerOf 0"
powerOf p n = case n `mod` p of
  0 -> 1 + powerOf p (n `div` p)
  _ -> 0

data DP = DP { isZero :: !Bool
             , minNum :: !Int
             , go :: !String }
             deriving (Show)

dpCost :: DP -> Int
dpCost (DP True  _ _) = 1
dpCost (DP False c _) = c

dp :: Int -> Int -> [UArray Int Int] -> DP
dp n p (row:rows) = (foldl' (dpRow n p) (dpFirstRow n p (I.elems row)) rows)!(n-1)

dpRow :: Int -> Int -> A.Array Int DP -> UArray Int Int -> A.Array Int DP
dpRow n p ups curs = I.listArray (0,n-1) $ scanl' step dpInit [1..n-1] where
  step (DP _        _       leftGo) n
    | curs!n == 0       = DP True 1 ('R':leftGo)
  step (DP leftZero leftNum leftGo) n
    | upCost < leftCost = DP upZero   upCost   ('D':upGo)
    | otherwise         = DP leftZero leftCost ('R':leftGo)
    where DP upZero upNum upGo = ups!n
          cur = powerOf p (curs!n)
          upCost = if upZero then 1 else cur + upNum
          leftCost = if leftZero then 1 else cur + leftNum
  dpInit = case curs!0 of
            0 -> DP True 1 ('D':go up)
            k -> DP False (powerOf p k + minNum up) ('D':go up)
  up = ups!0

dpFirstRow :: Int -> Int -> [Int] -> A.Array Int DP
dpFirstRow n p currs = I.listArray (0, n-1) $ zipWith zipper costs rs where
  zipper (dpZero, cost) dir = DP dpZero cost dir
  costs = tail $ scanl' step (False, 0) currs
  step (True, _)    _ = (True, 1)
  step (_,    cost) 0 = (True, 1)
  step (_,    cost) k = (False, let u = cost + powerOf p k in u `seq` u)
  rs = iterate ('R':) []

inputGrids :: IO (Int, [UArray Int Int])
inputGrids = do
  n <- readLn
  grids <- sequence $ replicate n $ do
    line <- B.getLine
    let ns = map (maybe (error "Read") fst) . map B.readInt . B.words $ line
    return $! I.listArray (0, n-1) ns
  return (n, grids)

main :: IO ()
main = do
  (n, grids) <- inputGrids
  let dp2 = dp n 2 grids
      dp5 = dp n 5 grids
  if dpCost dp2 <= dpCost dp5
    then (print . dpCost $ dp2) >> (putStrLn . reverse . go $ dp2)
    else (print . dpCost $ dp5) >> (putStrLn . reverse . go $ dp5)

module Main where

import qualified Data.Array.IArray as I
import qualified Data.Array as A
import Data.Array.Unboxed
import Data.List (foldl')
import qualified Data.ByteString.Char8 as B

scanl' :: (a -> b -> a) -> a -> [b] -> [a]
scanl' _ z  []    = [z]
scanl' f z (x:xs) = let u = f z x
                        ys = z:scanl' f u xs
                    in u `seq` ys `seq` ys

powerOf :: Int -> Int -> Int
powerOf _ 0 = error "powerOf 0"
powerOf p n = case n `mod` p of
  0 -> 1 + powerOf p (n `div` p)
  _ -> 0

data DP = DP { isZero :: !Bool
             , minNum :: !Int
             , go :: !String }
             deriving (Show)

dpCost :: DP -> Int
dpCost (DP True  _ _) = 1
dpCost (DP False c _) = c

dp :: Int -> Int -> [UArray Int Int] -> DP
dp n p (row:rows) = last $ foldl' (dpRow n p) (dpFirstRow n p row) rows

dpRow :: Int -> Int -> [DP] -> UArray Int Int -> [DP]
dpRow n p (up:ups) curs = scanl' step dpInit $ zip [1..] ups where
  step (DP _        _       leftGo) (k, _)
    | curs!k == 0       = DP True 1 ('R':leftGo)
  step (DP leftZero leftNum leftGo) (k, DP upZero upNum upGo)
    | upCost < leftCost = DP upZero   upCost   ('D':upGo)
    | otherwise         = DP leftZero leftCost ('R':leftGo)
    where k' = powerOf p (curs!k)
          upCost = if upZero then 1 else k' + upNum
          leftCost = if leftZero then 1 else k' + leftNum
  dpInit = case curs!0 of
            0 -> DP True 1 ('D':go up)
            k -> DP False (powerOf p k + minNum up) ('D':go up)

dpFirstRow :: Int -> Int -> UArray Int Int -> [DP]
dpFirstRow n p currs = zipWith zipper costs rs where
  zipper (dpZero, cost) dir = DP dpZero cost dir
  costs = tail $ scanl' step (False, 0) (I.elems currs)
  step (True, _)    _ = (True, 1)
  step (_,    cost) 0 = (True, 1)
  step (_,    cost) k = (False, cost + powerOf p k)
  rs = iterate ('R':) []

inputGrids :: IO (Int, [UArray Int Int])
inputGrids = do
  n <- readLn
  grids <- sequence $ replicate n $ do
    line <- B.getLine
    let ns = map (maybe (error "Read") fst) . map B.readInt . B.words $ line
    return (I.listArray (0, n-1) ns)
  return (n, grids)

main :: IO ()
main = do
  (n, grids) <- inputGrids
  let dp2 = dp n 2 grids
      dp5 = dp n 5 grids
  if dpCost dp2 <= dpCost dp5
    then (print . dpCost $ dp2) >> (putStrLn . reverse . go $ dp2)
    else (print . dpCost $ dp5) >> (putStrLn . reverse . go $ dp5)

module Main where

import qualified Data.Array.IArray as I
import qualified Data.Array as A
import Data.Array.Unboxed
import Data.List (foldl')
import qualified Data.ByteString.Char8 as B

scanl' :: (a -> b -> a) -> a -> [b] -> [a]
scanl' _ z  []    = [z]
scanl' f z (x:xs) = let u = f z x
                        ys = z:scanl' f u xs
                    in u `seq` ys `seq` ys

powerOf :: Int -> Int -> Int
powerOf _ 0 = error "powerOf 0"
powerOf p n = case n `mod` p of
  0 -> 1 + powerOf p (n `div` p)
  _ -> 0

data DP = DP { isZero :: !Bool
             , minNum :: !Int
             , go :: !String }
             deriving (Show)

dpCost :: DP -> Int
dpCost (DP True  _ _) = 1
dpCost (DP False c _) = c

dp :: Int -> Int -> [UArray Int Int] -> DP
dp n p (row:rows) = (foldl' (dpRow n p) (dpFirstRow n p (I.elems row)) rows)!(n-1)

dpRow :: Int -> Int -> A.Array Int DP -> UArray Int Int -> A.Array Int DP
dpRow n p ups curs = I.listArray (0,n-1) $ scanl' step dpInit [1..n-1] where
  step (DP _        _       leftGo) n
    | curs!n == 0       = DP True 1 ('R':leftGo)
  step (DP leftZero leftNum leftGo) n
    | upCost < leftCost = DP upZero   upCost   ('D':upGo)
    | otherwise         = DP leftZero leftCost ('R':leftGo)
    where DP upZero upNum upGo = ups!n
          cur = powerOf p (curs!n)
          upCost = if upZero then 1 else cur + upNum
          leftCost = if leftZero then 1 else cur + leftNum
  dpInit = case curs!0 of
            0 -> DP True 1 ('D':go up)
            k -> DP False (powerOf p k + minNum up) ('D':go up)
  up = ups!0

dpFirstRow :: Int -> Int -> [Int] -> A.Array Int DP
dpFirstRow n p currs = I.listArray (0, n-1) $ zipWith zipper costs rs where
  zipper (dpZero, cost) dir = DP dpZero cost dir
  costs = tail $ scanl' step (False, 0) currs
  step (True, _)    _ = (True, 1)
  step (_,    cost) 0 = (True, 1)
  step (_,    cost) k = (False, cost + powerOf p k)
  rs = iterate ('R':) []

inputGrids :: IO (Int, [UArray Int Int])
inputGrids = do
  n <- readLn
  grids <- sequence $ replicate n $ do
    line <- B.getLine
    let ns = map (maybe (error "Read") fst) . map B.readInt . B.words $ line
    return $! I.listArray (0, n-1) ns
  return (n, grids)

main :: IO ()
main = do
  (n, grids) <- inputGrids
  let dp2 = dp n 2 grids
      dp5 = dp n 5 grids
  if dpCost dp2 <= dpCost dp5
    then (print . dpCost $ dp2) >> (putStrLn . reverse . go $ dp2)
    else (print . dpCost $ dp5) >> (putStrLn . reverse . go $ dp5)

import Data.List
import Data.Maybe (maybeToList)
import Data.Functor ((<$>))
import Data.Function (on)
import qualified Data.Array.Unboxed as U
import qualified Data.Array.ST as ST
import qualified Data.ByteString.Char8 as B hiding (minimum)

getPows :: Int -> Int -> Int
getPows b x = case x `divMod` b of
                 (x', 0) -> 1 + getPows b x'
                 _ -> 0

solve :: Int -> U.UArray (Int, Int) Int -> Int -> (Int, String)
solve n mat b = (dp U.! (0, 0), findPath 0 0)
  where dp = ST.runSTUArray $ do
          let thunk = -1
          dp' <- ST.thaw (U.listArray ((0, 0), (n, n)) (repeat thunk) :: U.UArray (Int, Int) Int)

          let f i j = do
                tmp <- ST.readArray dp' (i, j)
                if tmp /= thunk
                  then return tmp
                  else do
                    ans <- f' i j
                    ST.writeArray dp' (i, j) $! ans
                    return ans

              f' i j
                | i == n-1 && j == n-1 = return gridWeight
                | i == n-1 = rpath
                | j == n-1 = dpath
                | otherwise = minimum <$> sequence [dpath, rpath]
                where gridWeight = getPows b $ mat U.! (i, j)
                      dpath = (gridWeight + ) <$> f (i+1) j
                      rpath = (gridWeight + ) <$> f i (j+1)

          ST.writeArray dp' (0, 0) =<< f 0 0
          return dp'

        findPath i j
          | i == n-1 = replicate (n-j-1) 'R'
          | j == n-1 = replicate (n-i-1) 'D'
          | otherwise =
            if dp U.! (i, j+1) > dp U.! (i+1, j)
            then 'D' : findPath (i+1) j
            else 'R' : findPath i (j+1)

readInt :: B.ByteString -> Int
readInt = maybe 0 fst . B.readInt

main :: IO ()
main = do
  n : mat' <- map readInt . B.words <$> B.getContents
  let zeroPath idx = (1, replicate x 'R' ++ replicate (n-1) 'D' ++ replicate (n-1-x) 'R')
        where x = idx `mod` n
      maybeZeroPath = maybeToList $ zeroPath <$> elemIndex 0 mat'
      mat = U.listArray ((0, 0), (n-1, n-1)) (map (\x -> if x == 0 then 10 else x) mat')

  let ans2 = solve n mat 2
      ans5 = solve n mat 5
      cands = maybeZeroPath ++ [ans2, ans5]
      (ansWeight, ansPath) = minimumBy (compare `on` fst) cands

  print ansWeight
  putStrLn ansPath

import Data.List
import Data.Maybe (maybeToList)
import Data.Functor ((<$>))
import Data.Function (on)
import Control.Monad (when)
import qualified Data.Array.Unboxed as U
import qualified Data.Array.ST as ST
import qualified Data.ByteString.Char8 as B hiding (minimum)

getPows :: Int -> Int -> Int
getPows b x = case x `divMod` b of
                 (x', 0) -> 1 + getPows b x'
                 _ -> 0

solve :: Int -> U.UArray (Int, Int) Int -> Int -> (Int, String)
solve n mat b = (dp U.! (0, 0), findPath 0 0)
  where dp = ST.runSTUArray $ do
          let thunk = -1
          dp' <- ST.thaw (U.listArray ((0, 0), (n, n)) (repeat thunk) :: U.UArray (Int, Int) Int)

          let f i j = do
                tmp <- ST.readArray dp' (i, j)
                when (tmp == thunk) $ ST.writeArray dp' (i, j) =<< f' i j
                ST.readArray dp' (i, j)

              f' i j
                | i == n-1 && j == n-1 = return gridWeight
                | i == n-1 = rpath
                | j == n-1 = dpath
                | otherwise = minimum <$> sequence [dpath, rpath]
                where gridWeight = getPows b $ mat U.! (i, j)
                      dpath = (gridWeight + ) <$> f (i+1) j
                      rpath = (gridWeight + ) <$> f i (j+1)

          ST.writeArray dp' (0, 0) =<< f 0 0
          return dp'

        findPath i j
          | i == n-1 = replicate (n-j-1) 'R'
          | j == n-1 = replicate (n-i-1) 'D'
          | otherwise =
            if dp U.! (i, j+1) > dp U.! (i+1, j)
            then 'D' : findPath (i+1) j
            else 'R' : findPath i (j+1)

readInt :: B.ByteString -> Int
readInt = maybe 0 fst . B.readInt

main :: IO ()
main = do
  n : mat' <- map readInt . B.words <$> B.getContents
  let zeroPath idx = (1, replicate x 'R' ++ replicate (n-1) 'D' ++ replicate (n-1-x) 'R')
        where x = idx `mod` n
      maybeZeroPath = maybeToList $ zeroPath <$> elemIndex 0 mat'
      mat = U.listArray ((0, 0), (n-1, n-1)) (map (\x -> if x == 0 then 10 else x) mat')

  let cands = maybeZeroPath ++ map (solve n mat) [2, 5]
      (ansWeight, ansPath) = minimumBy (compare `on` fst) cands

  print ansWeight
  putStrLn ansPath

import Data.List
import Data.Maybe (maybeToList)
import Data.Functor ((<$>))
import Data.Function (on)
import qualified Data.Array as A
import qualified Data.Array.Unboxed as U
import qualified Data.ByteString.Char8 as B

getPows :: Int -> Int -> Int
getPows b x = case x `divMod` b of
  (x', 0) -> 1 + getPows b x'
  _ -> 0

solve :: Int -> U.Array (Int, Int) Int -> (Int, String)
solve n mat = dp A.! (0, 0)
  where dp = A.array ((0, 0), (n-1, n-1)) [((i, j), f i j) | i <- [0..n-1], j <- [0..n-1]]
        f i j
          | i == n-1 && j == n-1 = (0, "")
          | i == n-1 = dpath
          | j == n-1 = rpath
          | otherwise = minimumBy (compare `on` fst) [dpath, rpath]
          where gridWeight = mat U.! (i, j)

                (dweight', dpath') = dp A.! (i, j+1)
                dpath = (gridWeight + dweight', 'R' : dpath')

                (rweight', rpath') = dp A.! (i+1, j)
                rpath = (gridWeight + rweight', 'D' : rpath')

main :: IO ()
main = do
  n : mat' <- map (maybe 0 fst . B.readInt) . B.words <$> B.getContents

  let mat = U.listArray ((0, 0), (n-1, n-1)) (map (\x -> if x == 0 then 10 else x) mat')

      mat2 = U.amap (getPows 2) mat
      mat5 = U.amap (getPows 5) mat

      zeroPath idx = (1, replicate x 'R' ++ replicate n 'D' ++ replicate (n-x) 'R')
        where x = idx `mod` n
      cands = [solve n mat2, solve n mat5] ++ maybeToList (zeroPath <$> elemIndex 0 mat')

      (ansWeight, ansPath) = minimumBy (compare `on` fst) cands

  print ansWeight
  putStrLn ansPath

import Control.Monad
import Data.Array
import Data.List
import Debug.Trace

data Path = Down | Right
data Cell = Cell Integer Integer Integer -- Cost Up left
	deriving (Show)

up (Cell _ u _) = u
left (Cell _ _ l) = l
cost (Cell c _ _) = c

noVal = 10000000

getInput = do
	n <- (liftM read) getLine
	lines <- sequence $ replicate n getLine
	let arr = map words lines
	return $ (n, array ((1, 1), (n, n)) [((i, j), v) | i <- [1..n], j <- [1..n], let v = read $ (arr !! (j - 1)) !! (i - 1) :: Integer])

trailingZeroes :: Integer -> Int
trailingZeroes x = length $ takeWhile (== '0') $ (reverse . show) x

calcPaths arr n divisor = a
		where
			a = array ((1, 1), (n, n)) [((i, j), v) | i <- [1..n], j <- [1..n], let v = calcCell i j]
			calcCell i j
				| (i == 1) && (j == 1) = Cell current noVal noVal
				| (i == 1) && (j > 1) = Cell (normalize current costUp) (normalize current costUp) noVal
				| (i > 1) && (j == 1) = Cell (normalize current costLeft) noVal (normalize current costLeft)
				| (i > 1) && (j > 1) = Cell (normalize current $ minimum [costLeft, costUp]) (normalize current costUp) (normalize current costLeft)
				where
					costUp = cost (a ! (i, j - 1))
					costLeft = cost (a ! (i - 1, j))
					current = if (arr ! (i, j) /= 0)
						then powerOf divisor (arr ! (i, j))
						else noVal
					normalize value addend = (if value == noVal then 1 else value + addend)

powerOf :: Integer -> Integer -> Integer
powerOf q p = toInteger $ length $ takeWhile (== 0) $ map ((flip mod) q) $ iterate ((flip div) q) p

getPath arr1 arr2 n = reverse $ getPath' (n, n)
	where
		getPath' (i, j)
			| (i, j) == (1, 1) = ""
			| otherwise = if max (up cell_1) (up cell_2) < max (left cell_1) (left cell_2)
				then 'D' : getPath' (i, j - 1)
				else 'R' : getPath' (i - 1, j)
			where
				cell_1 = arr1 ! (i, j)
				cell_2 = arr2 ! (i, j)

main = do
	(n, matrix) <- getInput
	--print matrix
	let paths2 = calcPaths matrix n 2
	let paths5 = calcPaths matrix n 5
{-	putStrLn "------"
	print paths2
	putStrLn "------"
	print paths5
	putStrLn "------"
	-}

	print $ min (cost $ paths2 ! (n, n)) (cost $ paths5 ! (n, n))
	putStrLn $ getPath paths2 paths5 n

import Control.Monad
import Data.Array
import Data.List
import Debug.Trace

data Path = Down | Right
data Cell = Cell Integer Integer Integer -- Cost Up left
	deriving (Show)

up (Cell _ u _) = u
left (Cell _ _ l) = l
cost (Cell c _ _) = c

noVal = 10000000

getInput = do
	n <- (liftM read) getLine
	lines <- sequence $ replicate n getLine
	let arr = map words lines
	return $ (n, array ((1, 1), (n, n)) [((i, j), v) | i <- [1..n], j <- [1..n], let v = read $ (arr !! (j - 1)) !! (i - 1) :: Integer])

trailingZeroes :: Integer -> Int
trailingZeroes x = length $ takeWhile (== '0') $ (reverse . show) x

calcPaths arr n divisor = a
		where
			a = array ((1, 1), (n, n)) [((i, j), v) | i <- [1..n], j <- [1..n], let v = calcCell i j]
			calcCell i j
				| (i == 1) && (j == 1) = Cell current noVal noVal
				| (i == 1) && (j > 1) = Cell (normalize current costUp) (normalize current costUp) noVal
				| (i > 1) && (j == 1) = Cell (normalize current costLeft) noVal (normalize current costLeft)
				| (i > 1) && (j > 1) = Cell (normalize current $ minimum [costLeft, costUp]) (normalize current costUp) (normalize current costLeft)
				where
					costUp = cost (a ! (i, j - 1))
					costLeft = cost (a ! (i - 1, j))
					current = if (arr ! (i, j) /= 0)
						then powerOf divisor (arr ! (i, j))
						else noVal
					normalize value addend = (if value == noVal then 1 else value + addend)

powerOf :: Integer -> Integer -> Integer
powerOf q p = toInteger $ length $ takeWhile (== 0) $ map ((flip mod) q) $ iterate ((flip div) q) p

getPath arr1 arr2 n = reverse $ getPath' (n, n)
	where
		getPath' (i, j)
			| (i, j) == (1, 1) = ""
			| otherwise = if decide (up cell_1) (up cell_2) (left cell_1) (left cell_2)
				then 'D' : getPath' (i, j - 1)
				else 'R' : getPath' (i - 1, j)
			where
				cell_1 = arr1 ! (i, j)
				cell_2 = arr2 ! (i, j)
				decide cu1 cu2 cl1 cl2 =
					case min cu1 cu2 `compare` min cl1 cl2 of
						LT -> True
						GT -> False
						EQ -> max cu1 cu2 < max cl1 cl2

main = do
	(n, matrix) <- getInput
--	print matrix
	let paths2 = calcPaths matrix n 2
	let paths5 = calcPaths matrix n 5
--	putStrLn "------"
--	print paths2
--	putStrLn "------"
--	print paths5
--	putStrLn "------"

	print $ min (cost $ paths2 ! (n, n)) (cost $ paths5 ! (n, n))
	putStrLn $ getPath paths2 paths5 n

import Control.Monad
import Data.Array
import Data.List

data Path = Down | Right
data Cell = Cell Integer Integer Integer -- Cost Up left
	deriving (Show)

up (Cell _ u _) = u
left (Cell _ _ l) = l
cost (Cell c _ _) = c

noVal = 1000000

getInput = do
	n <- (liftM read) getLine
	lines <- sequence $ replicate n getLine
	let arr = map words lines
	return $ (n, array ((1, 1), (n, n)) [((i, j), v) | i <- [1..n], j <- [1..n], let v = read $ (arr !! (j - 1)) !! (i - 1) :: Integer])

trailingZeroes :: Integer -> Int
trailingZeroes x = length $ takeWhile (== '0') $ (reverse . show) x

calcPaths arr n = a
		where
			a = array ((1, 1), (n, n)) [((i, j), v) | i <- [1..n], j <- [1..n], let v = calcCell i j]
			calcCell i j
				| (i == 1) && (j == 1) = Cell (arr ! (i, j)) noVal noVal
				| (i == 1) && (j > 1) = Cell costUp costUp noVal
				| (i > 1) && (j == 1) = Cell costLeft noVal costLeft
				| (i > 1) && (j > 1) = Cell (minimumBy (\x y -> trailingZeroes x `compare` trailingZeroes y ) [costUp, costLeft]) costUp costLeft
				where
					costUp = (arr ! (i, j) * cost (a ! (i, j - 1)))
					costLeft = (arr ! (i, j) * cost (a ! (i - 1, j)))

getPath arr n = reverse $ getPath' arr n (n, n)
	where
		getPath' arr n (i, j)
			| (i, j) == (1, 1) = ""
			| otherwise = if (trailingZeroes . up) cell < (trailingZeroes . left) cell
				then 'D' : getPath' arr n (i, j - 1)
				else 'R' : getPath' arr n (i - 1, j)
			where cell = arr ! (i, j)

main = do
	(n, matrix) <- getInput
	let paths = calcPaths matrix n
	--print paths
	print $ trailingZeroes $ cost $ paths ! (n, n)
	putStrLn $ getPath paths n

import Control.Monad
import Data.Array
import Data.List

data Path = Down | Right
data Cell = Cell Integer Integer Integer -- Cost Down Right
	deriving (Show)

down (Cell _ d _) = d
right (Cell _ _ r) = r
cost (Cell c _ _) = c
value (Cell _ d r) = undefined

noVal = 1000000

getInput = do
	n <- (liftM read) getLine
	lines <- sequence $ replicate n getLine
	let arr = map words lines
	return $ (n, array ((1, 1), (n, n)) [((i, j), v) | i <- [1..n], j <- [1..n], let v = read $ (arr !! (i - 1)) !! (j - 1) :: Integer])

trailingZeroes :: Integer -> Int
trailingZeroes x = length $ takeWhile (== '0') $ (reverse . show) x

calcPaths arr n = a
		where
			a = array ((1, 1), (n, n)) [((i, j), v) | i <- [1..n], j <- [1..n], let v = calcCell i j]
			calcCell i j
				| (i == n) && (j == n) = Cell (arr ! (i, j)) noVal noVal
				| (i == n) && (j < n) = Cell costDown costDown  noVal
				| (i < n) && (j == n) = Cell costRight noVal costRight
				| (i < n) && (j < n) = Cell (minimumBy (\x y -> trailingZeroes x `compare` trailingZeroes y ) [costDown, costRight]) costDown costRight
				where
					costDown = (arr ! (i, j) * cost (a ! (i, j + 1)))
					costRight = (arr ! (i, j) * cost (a ! (i + 1, j)))

getPath arr n = getPath' arr n (1, 1)
	where
		getPath' arr n (i, j)
			| (i, j) == (n, n) = ""
			| otherwise = if (trailingZeroes . down) cell < (trailingZeroes . right) cell
				then 'R' : getPath' arr n (i, j + 1)
				else 'D' : getPath' arr n (i + 1, j)
			where cell = arr ! (i, j)

main = do
	(n, matrix) <- getInput
	let paths = calcPaths matrix n
	print $ trailingZeroes $ cost $ paths ! (1, 1)
	putStrLn $ getPath paths n

{-# LANGUAGE BangPatterns #-}

import Control.Monad
import Data.Array
import qualified Data.Array as A
import qualified Data.Array.Unboxed as U
import qualified Data.ByteString as B
import qualified Data.ByteString.Char8 as B8
import Data.List
import Debug.Trace
import Control.Monad.ST
import Data.Array.ST

data Path = PathUp | PathLeft | NoPath
	deriving (Show, Eq)
--data Cell = Cell !Int !Path -- Cost Path
--	deriving (Show)

--cost (Cell c _) = c

path (i, j) arr
	| (i == 1) && (j == 1) = NoPath
	| (i == 1) && (j > 1) = PathUp
	| (i > 1) && (j == 1) = PathLeft
	| (i > 1) && (j > 1) = if up <= left then PathUp else PathLeft
		where
			up = arr ! (i, j - 1)
			left = arr ! (i - 1, j)

noVal = -1

getInput = do
	n <- (liftM read) getLine
	lines <- sequence $ replicate n B.getLine
	let arr = map (B.split 0x20) lines
	return $! (n, U.array ((1, 1), (n, n)) [((i, j), v) | (line, j) <- (zip arr [1..n]), (num, i) <- (zip line [1..n]), let !v = readNumber num])
	where
		readNumber x = case B8.readInt x of
			Just (!num, _) -> num
			Nothing -> error "Unable to read input"

trailingZeroes :: Int -> Int
trailingZeroes x = length $ takeWhile (== '0') $ (reverse . show) x

calcPaths :: U.Array (Int, Int) Int -> Int -> Int -> Array (Int, Int) Int
calcPaths arr n divisor = runSTArray $ do
	a <- newArray ((1, 1), (n, n)) 0 :: ST s (STArray s (Int,Int) Int)
	forM_ [1..n] $! \diag -> do
		let indices = diagIndices $! diag
		forM_ indices $! \(i, j) -> case () of
			_ | (i == 1) && (j == 1) -> writeArray a (i, j) current
				| (i == 1) && (j > 1) -> do
					up <- readArray a (i, j - 1)
					writeArray a (i, j) $! normalize current up
				| (i > 1) && (j == 1) -> do
					left <- readArray a (i - 1, j)
					writeArray a (i, j) $! normalize current left
				| (i > 1) && (j > 1) -> do
					up <- readArray a (i, j - 1)
					left <- readArray a (i - 1, j)
					writeArray a (i, j) $! if left <= up
						then normalize current left
						else normalize current up
				where
					current = if (arr U.! (i, j) /= 0)
						then powerOf divisor (arr ! (i, j))
						else noVal
	return a
	where
		normalize !value !addend = (if value == noVal then 1 else value + addend)
		diagIndices diag = if diag == n then [(diag, diag)] else
			zip [diag..n] (repeat diag) ++ zip (repeat diag) [(diag + 1)..n]

powerOf :: Int -> Int -> Int
powerOf q p = powerOf' q p 0
	where
		powerOf' q p n = if p `mod` q /= 0 then n else powerOf' q (p `div` q) (n + 1)

getPath arr n = reverse $ getPath' (n, n)
	where
		getPath' (i, j)
			| (i, j) == (1, 1) = ""
			| otherwise = if path (i,j) arr == PathUp
				then 'D' : getPath' (i, j - 1)
				else 'R' : getPath' (i - 1, j)

main = do
	(n, matrix) <- getInput
	let paths2 = calcPaths matrix n 2
	let cost2 = (paths2 ! (n, n))
	path2 <- do
		return $ getPath paths2 n

	let paths5 = calcPaths matrix n 5
	let cost5 = (paths5 ! (n, n))
	path5 <- do
		return $ getPath paths5 n

	if cost2 < cost5
		then do
			print cost2
			putStrLn path2
		else do
			print cost5
			putStrLn path5

import Control.Monad
import Data.Array
import Data.List
import Debug.Trace

data Path = Down | Right
data Cell = Cell Integer Integer Integer -- Cost Up left
	deriving (Show)

up (Cell _ u _) = u
left (Cell _ _ l) = l
cost (Cell c _ _) = c

noVal = 10000000

getInput = do
	n <- (liftM read) getLine
	lines <- sequence $ replicate n getLine
	let arr = map words lines
	return $ (n, array ((1, 1), (n, n)) [((i, j), v) | i <- [1..n], j <- [1..n], let v = read $ (arr !! (j - 1)) !! (i - 1) :: Integer])

trailingZeroes :: Integer -> Int
trailingZeroes x = length $ takeWhile (== '0') $ (reverse . show) x

calcPaths arr n divisor = a
		where
			a = array ((1, 1), (n, n)) [((i, j), v) | i <- [1..n], j <- [1..n], let v = calcCell i j]
			calcCell i j
				| (i == 1) && (j == 1) = Cell current noVal noVal
				| (i == 1) && (j > 1) = Cell (normalize current costUp) (normalize current costUp) noVal
				| (i > 1) && (j == 1) = Cell (normalize current costLeft) noVal (normalize current costLeft)
				| (i > 1) && (j > 1) = Cell (normalize current $ minimum [costLeft, costUp]) (normalize current costUp) (normalize current costLeft)
				where
					costUp = cost (a ! (i, j - 1))
					costLeft = cost (a ! (i - 1, j))
					current = if (arr ! (i, j) /= 0)
						then powerOf divisor (arr ! (i, j))
						else noVal
					normalize value addend = (if value == noVal then 1 else value + addend)

powerOf :: Integer -> Integer -> Integer
powerOf q p = toInteger $ length $ takeWhile (== 0) $ map ((flip mod) q) $ iterate ((flip div) q) p

getPath arr1 arr2 n = reverse $ getPath' (n, n)
	where
		getPath' (i, j)
			| (i, j) == (1, 1) = ""
			| otherwise = if min (up cell_1) (up cell_2) < min (left cell_1) (left cell_2)
				then 'D' : getPath' (i, j - 1)
				else 'R' : getPath' (i - 1, j)
			where
				cell_1 = arr1 ! (i, j)
				cell_2 = arr2 ! (i, j)

main = do
	(n, matrix) <- getInput
--	print matrix
	let paths2 = calcPaths matrix n 2
	let paths5 = calcPaths matrix n 5
{-
	putStrLn "------"
	print paths2
	putStrLn "------"
	print paths5
	putStrLn "------"
-}

	print $ min (cost $ paths2 ! (n, n)) (cost $ paths5 ! (n, n))
	putStrLn $ getPath paths2 paths5 n

{-# LANGUAGE BangPatterns #-}

import Control.Monad
import Data.Array
import qualified Data.Array as A
import qualified Data.Array.Unboxed as U
import qualified Data.ByteString as B
import qualified Data.ByteString.Char8 as B8
import Data.List
import Debug.Trace
import Control.Monad.ST
import Data.Array.ST

data Path = PathUp | PathLeft | NoPath
	deriving (Show, Eq)
--data Cell = Cell !Int !Path -- Cost Path
--	deriving (Show)

--cost (Cell c _) = c

path (i, j) arr
	| (i == 1) && (j == 1) = NoPath
	| (i == 1) && (j > 1) = PathUp
	| (i > 1) && (j == 1) = PathLeft
	| (i > 1) && (j > 1) = if up == noVal then PathUp
	else if left == noVal then PathLeft else
		if up <= left then PathUp else PathLeft
			where
				up = arr ! (i, j - 1)
				left = arr ! (i - 1, j)

noVal = -1

getInput = do
	n <- (liftM read) getLine
	lines <- sequence $ replicate n B.getLine
	let arr = map (B.split 0x20) lines
	return $! (n, U.array ((1, 1), (n, n)) [((i, j), v) | (line, j) <- (zip arr [1..n]), (num, i) <- (zip line [1..n]), let !v = readNumber num])
	where
		readNumber x = case B8.readInt x of
			Just (!num, _) -> num
			Nothing -> error "Unable to read input"

calcPaths :: U.Array (Int, Int) Int -> Int -> Int -> Array (Int, Int) Int
calcPaths arr n divisor = runSTArray $ do
	a <- newArray ((1, 1), (n, n)) 0 :: ST s (STArray s (Int,Int) Int)
	forM_ [1..n] $! \diag -> do
		let indices = diagIndices $! diag
		forM_ indices $! \(i, j) -> case () of
			_ | (i == 1) && (j == 1) -> writeArray a (i, j) current
				| (i == 1) && (j > 1) -> do
					up <- readArray a (i, j - 1)
					writeArray a (i, j) $! normalize current up
				| (i > 1) && (j == 1) -> do
					left <- readArray a (i - 1, j)
					writeArray a (i, j) $! normalize current left
				| (i > 1) && (j > 1) -> do
					up <- readArray a (i, j - 1)
					left <- readArray a (i - 1, j)
					writeArray a (i, j) $! if left <= up
						then normalize current left
						else normalize current up
				where
					current = if (arr U.! (i, j) /= 0)
						then powerOf divisor (arr ! (i, j))
						else noVal
	return a
	where
		normalize !value !addend = (if value == noVal || addend == noVal then noVal else value + addend)
		diagIndices diag = if diag == n then [(diag, diag)] else
			zip [diag..n] (repeat diag) ++ zip (repeat diag) [(diag + 1)..n]

powerOf :: Int -> Int -> Int
powerOf q p = powerOf' q p 0
	where
		powerOf' q p n = if p `mod` q /= 0 then n else powerOf' q (p `div` q) (n + 1)

getPath arr n = reverse $ getPath' (n, n)
	where
		getPath' (i, j)
			| (i, j) == (1, 1) = ""
			| otherwise = if path (i,j) arr == PathUp
				then 'D' : getPath' (i, j - 1)
				else 'R' : getPath' (i - 1, j)

main = do
	(n, matrix) <- getInput
	let paths2 = calcPaths matrix n 2
	let cost2 = (paths2 ! (n, n))
	path2 <- do
		return $ getPath paths2 n

	let paths5 = calcPaths matrix n 5
	let cost5 = (paths5 ! (n, n))
	path5 <- do
		return $ getPath paths5 n

	if cost2 < cost5
		then do
			if cost2 < 0 then print 1 else print cost2
			putStrLn path2
		else do
			if cost5 < 0 then print 1 else print cost5
			putStrLn path5

import Control.Monad
import Data.Array
import Data.List

data Path = Down | Right
data Cell = Cell Int Int Int -- Cost Down Right
	deriving (Show)

down (Cell _ d _) = d
right (Cell _ _ r) = r
cost (Cell c _ _) = c
value (Cell _ d r) = undefined

noVal = 1000000

getInput = do
	n <- (liftM read) getLine
	lines <- sequence $ replicate n getLine
	let arr = map words lines
	return $ (n, array ((1, 1), (n, n)) [((i, j), v) | i <- [1..n], j <- [1..n], let v = read $ (arr !! (i - 1)) !! (j - 1) :: Int])

trailingZeroes :: Int -> Int
trailingZeroes x = length $ takeWhile (== '0') $ (reverse . show) x

calcPaths arr n = a
		where
			a = array ((1, 1), (n, n)) [((i, j), v) | i <- [1..n], j <- [1..n], let v = calcCell i j]
			calcCell i j
				| (i == n) && (j == n) = Cell (arr ! (i, j)) noVal noVal
				| (i == n) && (j < n) = Cell costDown costDown  noVal
				| (i < n) && (j == n) = Cell costRight noVal costRight
				| (i < n) && (j < n) = Cell (minimumBy (\x y -> trailingZeroes x `compare` trailingZeroes y ) [costDown, costRight]) costDown costRight
				where
					costDown = (arr ! (i, j) * cost (a ! (i, j + 1)))
					costRight = (arr ! (i, j) * cost (a ! (i + 1, j)))

getPath arr n = getPath' arr n (1, 1)
	where
		getPath' arr n (i, j)
			| (i, j) == (n, n) = ""
			| otherwise = if (trailingZeroes . down) cell < (trailingZeroes . right) cell
				then 'R' : getPath' arr n (i, j + 1)
				else 'D' : getPath' arr n (i + 1, j)
			where cell = arr ! (i, j)

main = do
	(n, matrix) <- getInput
	let paths = calcPaths matrix n
	print $ trailingZeroes $ cost $ paths ! (1, 1)
	putStrLn $ getPath paths n

import Control.Monad
import Data.Array
import Data.List
import Debug.Trace

data Path = Down | Right
data Cell = Cell Integer Integer Integer -- Cost Up left
	deriving (Show)

up (Cell _ u _) = u
left (Cell _ _ l) = l
cost (Cell c _ _) = c

noVal = 10000000

getInput = do
	n <- (liftM read) getLine
	lines <- sequence $ replicate n getLine
	let arr = map words lines
	return $ (n, array ((1, 1), (n, n)) [((i, j), v) | i <- [1..n], j <- [1..n], let v = read $ (arr !! (j - 1)) !! (i - 1) :: Integer])

trailingZeroes :: Integer -> Int
trailingZeroes x = length $ takeWhile (== '0') $ (reverse . show) x

calcPaths arr n divisor = a
		where
			a = array ((1, 1), (n, n)) [((i, j), v) | i <- [1..n], j <- [1..n], let v = calcCell i j]
			calcCell i j
				| (i == 1) && (j == 1) = Cell current noVal noVal
				| (i == 1) && (j > 1) = Cell (normalize current costUp) (normalize current costUp) noVal
				| (i > 1) && (j == 1) = Cell (normalize current costLeft) noVal (normalize current costLeft)
				| (i > 1) && (j > 1) = Cell (normalize current $ minimum [costLeft, costUp]) (normalize current costUp) (normalize current costLeft)
				where
					costUp = cost (a ! (i, j - 1))
					costLeft = cost (a ! (i - 1, j))
					current = if (arr ! (i, j) /= 0)
						then powerOf divisor (arr ! (i, j))
						else noVal
					normalize value addend = (if value == noVal then 1 else value + addend)

powerOf :: Integer -> Integer -> Integer
powerOf q p = toInteger $ length $ takeWhile (== 0) $ map ((flip mod) q) $ iterate ((flip div) q) p

getPath arr1 arr2 n = reverse $ getPath' (n, n) (0, 0)
	where
		getPath' (i, j) (fives, twos)
			| (i, j) == (1, 1) = ""
			| otherwise = if decide (up cell_1) (up cell_2) (left cell_1) (left cell_2)
				then 'D' : getPath' (i, j - 1) (fives, twos)
				else 'R' : getPath' (i - 1, j) (fives, twos)
			where
				cell_1 = arr1 ! (i, j)
				cell_2 = arr2 ! (i, j)
				decide cu1 cu2 cl1 cl2 =
					if min (cl1 + twos) (cl2 + fives) < min (cu1 + twos) (cu2 + fives)
						then False
						else True

main = do
	(n, matrix) <- getInput
--	print matrix
	let paths2 = calcPaths matrix n 2
	let paths5 = calcPaths matrix n 5
{-	putStrLn "------"
	print paths2
	putStrLn "------"
	print paths5
	putStrLn "------" -}

	print $ min (cost $ paths2 ! (n, n)) (cost $ paths5 ! (n, n))
	putStrLn $ getPath paths2 paths5 n

import Control.Monad
import Data.Array
import Data.List
import Debug.Trace

data Path = Down | Right
data Cell = Cell Integer Integer Integer -- Cost Up left
	deriving (Show)

up (Cell _ u _) = u
left (Cell _ _ l) = l
cost (Cell c _ _) = c

noVal = 10000000

getInput = do
	n <- (liftM read) getLine
	lines <- sequence $ replicate n getLine
	let arr = map words lines
	return $ (n, array ((1, 1), (n, n)) [((i, j), v) | i <- [1..n], j <- [1..n], let v = read $ (arr !! (j - 1)) !! (i - 1) :: Integer])

trailingZeroes :: Integer -> Int
trailingZeroes x = length $ takeWhile (== '0') $ (reverse . show) x

calcPaths arr n divisor = a
		where
			a = array ((1, 1), (n, n)) [((i, j), v) | i <- [1..n], j <- [1..n], let v = calcCell i j]
			calcCell i j
				| (i == 1) && (j == 1) = Cell current noVal noVal
				| (i == 1) && (j > 1) = Cell (if current == noVal then 1 else current + costUp) costUp noVal
				| (i > 1) && (j == 1) = Cell (if current == noVal then 1 else current + costLeft) noVal costLeft
				| (i > 1) && (j > 1) = Cell (if current == noVal then 1 else current + minimum [costLeft, costUp]) costUp costLeft
				where
					costUp = cost (a ! (i, j - 1))
					costLeft = cost (a ! (i - 1, j))
					current = if (arr ! (i, j) /= 0)
						then powerOf divisor (arr ! (i, j))
						else noVal

powerOf :: Integer -> Integer -> Integer
powerOf q p = toInteger $ length $ takeWhile (== 0) $ map ((flip mod) q) $ iterate ((flip div) q) p

getPath arr1 arr2 n = reverse $ getPath' (n, n)
	where
		getPath' (i, j)
			| (i, j) == (1, 1) = ""
			| otherwise = if max (up cell_1) (up cell_2) < max (left cell_1) (left cell_2)
				then 'D' : getPath' (i, j - 1)
				else 'R' : getPath' (i - 1, j)
			where
				cell_1 = arr1 ! (i, j)
				cell_2 = arr2 ! (i, j)

main = do
	(n, matrix) <- getInput
	let paths2 = calcPaths matrix n 2
	let paths5 = calcPaths matrix n 5

	print $ min (cost $ paths2 ! (n, n)) (cost $ paths5 ! (n, n))
	putStrLn $ getPath paths2 paths5 n

import Control.Monad
import Data.Array
import Data.List
import Debug.Trace

data Path = Down | Right
data Cell = Cell Integer Integer Integer -- Cost Up left
	deriving (Show)

up (Cell _ u _) = u
left (Cell _ _ l) = l
cost (Cell c _ _) = c

noVal = 10000000

getInput = do
	n <- (liftM read) getLine
	lines <- sequence $ replicate n getLine
	let arr = map words lines
	return $ (n, array ((1, 1), (n, n)) [((i, j), v) | i <- [1..n], j <- [1..n], let v = read $ (arr !! (j - 1)) !! (i - 1) :: Integer])

trailingZeroes :: Integer -> Int
trailingZeroes x = length $ takeWhile (== '0') $ (reverse . show) x

calcPaths arr n divisor = a
		where
			a = array ((1, 1), (n, n)) [((i, j), v) | i <- [1..n], j <- [1..n], let v = calcCell i j]
			calcCell i j
				| (i == 1) && (j == 1) = Cell current noVal noVal
				| (i == 1) && (j > 1) = Cell (normalize current costUp) (normalize current costUp) noVal
				| (i > 1) && (j == 1) = Cell (normalize current costLeft) noVal (normalize current costLeft)
				| (i > 1) && (j > 1) = Cell (normalize current $ minimum [costLeft, costUp]) (normalize current costUp) (normalize current costLeft)
				where
					costUp = cost (a ! (i, j - 1))
					costLeft = cost (a ! (i - 1, j))
					current = if (arr ! (i, j) /= 0)
						then powerOf divisor (arr ! (i, j))
						else noVal
					normalize value addend = (if value == noVal then 1 else value + addend)

powerOf :: Integer -> Integer -> Integer
powerOf q p = toInteger $ length $ takeWhile (== 0) $ map ((flip mod) q) $ iterate ((flip div) q) p

getPath arr1 arr2 n = reverse $ getPath' (n, n)
	where
		getPath' (i, j)
			| (i, j) == (1, 1) = ""
			| otherwise = if decide (up cell_1) (up cell_2) (left cell_1) (left cell_2)
				then 'D' : getPath' (i, j - 1)
				else 'R' : getPath' (i - 1, j)
			where
				cell_1 = arr1 ! (i, j)
				cell_2 = arr2 ! (i, j)
				decide cu1 cu2 cl1 cl2 =
					case max cu1 cu2 `compare` max cl1 cl2 of
						LT -> True
						GT -> False
						EQ -> min cu1 cu2 < min cl1 cl2

main = do
	(n, matrix) <- getInput
--	print matrix
	let paths2 = calcPaths matrix n 2
	let paths5 = calcPaths matrix n 5
--	putStrLn "------"
--	print paths2
--	putStrLn "------"
--	print paths5
--	putStrLn "------"

	print $ min (cost $ paths2 ! (n, n)) (cost $ paths5 ! (n, n))
	putStrLn $ getPath paths2 paths5 n

import Control.Monad
import Data.Array
import Data.List

data Path = Down | Right
data Cell = Cell Int Int Int -- Cost Down Right
	deriving (Show)

down (Cell _ d _) = d
right (Cell _ _ r) = r
cost (Cell c _ _) = c
value (Cell _ d r) = undefined

noVal = 1000000

getInput = do
	n <- (liftM read) getLine
	lines <- sequence $ replicate n getLine
	let arr = map words lines
	return $ (n, array ((1, 1), (n, n)) [((i, j), v) | i <- [1..n], j <- [1..n], let v = read $ (arr !! (i - 1)) !! (j - 1) :: Int])

trailingZeroes :: Int -> Int
trailingZeroes x = length $ takeWhile (== '0') $ (reverse . show) x

calcPaths arr n = a
		where
			a = array ((1, 1), (n, n)) [((i, j), v) | i <- [1..n], j <- [1..n], let v = calcCell i j]
			calcCell i j
				| (i == n) && (j == n) = Cell (arr ! (i, j)) noVal noVal
				| (i == n) && (j < n) = Cell costDown costDown  noVal
				| (i < n) && (j == n) = Cell costRight noVal costRight
				| (i < n) && (j < n) = Cell (minimumBy (\x y -> trailingZeroes x `compare` trailingZeroes y ) [costDown, costRight]) costDown costRight
				where
					costDown = (arr ! (i, j) * cost (a ! (i, j + 1)))
					costRight = (arr ! (i, j) * cost (a ! (i + 1, j)))

getPath arr n = getPath' arr n (1, 1)
	where
		getPath' arr n (i, j)
			| (i, j) == (n, n) = ""
			| otherwise = if (trailingZeroes . down) cell < (trailingZeroes . right) cell
				then 'R' : getPath' arr n (i, j + 1)
				else 'D' : getPath' arr n (i + 1, j)
			where cell = arr ! (i, j)

main = do
	(n, matrix) <- getInput
	print matrix
	let paths = calcPaths matrix n
	print $ paths ! (1, 1)
	print $ getPath paths n

import Data.List (foldl')
import Control.DeepSeq
main = do
  n <- readLn
  ns <- fmap (chunksOf n . map read . words) getContents
  let start = ((0 :: Int,""),(0,""))
      iv = start : replicate (n-1) junk
      (m,p) =  uncurry min $last $ foldl' dp iv ns
  print m
  putStrLn (tail $ reverse p)
junk = ((maxBound,"E"),(maxBound,"E"))
dp prev cur = force $ go junk prev cur where
  go _ _ [] = []
  go ((l2,l2p),(l5,l5p)) (((u2,u2p),(u5,u5p)):u) (x:xs) =
    b2 `seq` b5 `seq` (b : go b u xs) where
      b = (b2,b5)
      n2 = factors 2 x
      n5 = factors 5 x
      b2 = min ((l2+n2),('R' : l2p)) ((u2+n2),('D' : u2p))
      b5 = min ((l5+n5),('R' : l5p)) ((u5+n5),('D' : u5p))
factors n x = go x 0 where
  go x a | r == 0 = go q $! a + 1
         | otherwise = a
    where (q,r) = x `divMod` n
chunksOf _ [] = []
chunksOf n xs = l : chunksOf n r where (l,r) = splitAt n xs

import qualified Data.ByteString.Char8 as B
import Data.List (foldl')
import Data.Array.IArray
import Data.Array.ST.Safe (STArray,STUArray,newArray,readArray,writeArray)
import Data.STRef (newSTRef,readSTRef,writeSTRef)
import Control.Monad (when)
import Control.Monad.ST.Safe (ST,runST)
main = do
  (n:ns) <- fmap (map read' . B.words) B.getContents
  let prep = do
        m2 <- newArray (0,n) (maxBound `div` 2) :: ST s (STUArray s Int Int)
        p2 <- newArray (0,n) "E"                :: ST s (STArray s Int String)
        writeArray m2 1 0
        writeArray p2 1 ""
        return (m2,p2)
  let dp ns = runST $ do
        zero <- newSTRef Nothing
        (m2,p2) <- prep
        (m5,p5) <- prep
        let dp' ns = go ns 1 where
              go [] _ = return ()
              go (x:xs) i = do
                when (x == 0) $ writeSTRef zero (Just i)
                l2  <- readArray m2 (i-1)
                l2p <- readArray p2 (i-1)
                l5  <- readArray m5 (i-1)
                l5p <- readArray p5 (i-1)
                u2  <- readArray m2  i
                u2p <- readArray p2  i
                u5  <- readArray m5  i
                u5p <- readArray p5  i
                let n2 = factors 2 x
                    n5 = factors 5 x
                    (e2,e2p) = min ((l2+n2),('R':l2p)) ((u2+n2),('D':u2p))
                    (e5,e5p) = min ((l5+n5),('R':l5p)) ((u5+n5),('D':u5p))
                writeArray m2 i e2
                writeArray p2 i e2p
                writeArray m5 i e5
                writeArray p5 i e5p
                go xs $! i+1
        mapM_ dp' ns
        b2  <- readArray m2 n
        b2p <- readArray p2 n
        b5  <- readArray m5 n
        b5p <- readArray p5 n
        z <- readSTRef zero
        let (m,p) = min (b2,b2p) (b5,b5p)
        return $ case z of
          Nothing -> (m,p)
          Just j -> min (m,p) (1,replicate (j-1) 'R' ++
                                 replicate (n-1) 'D' ++
                                 replicate (n-j) 'R')
      (m,p) = dp (chunksOf n ns)
  print m
  putStrLn (tail $ reverse p)
{-# INLINE factors #-}
factors _ 0 = 1
factors n x = go x 0 where
  go x a | r == 0    = go q $! a + 1
         | otherwise = a
    where (q,r) = x `divMod` n
{-# INLINE chunksOf #-}
chunksOf n = go where
  go [] = []
  go xs = l : go r where (l,r) = splitAt n xs
{-# INLINE read' #-}
read' s = r where Just (r,_) = B.readInt s

import Data.List
import Control.Monad

main = do
  n <- readLn
  r <- liftM (solve . parse) (replicateM n getLine)
  print r

parse = map (map read . words)
big = 60000

solve ls = (z,tail (reverse t))
    where i = ((0,""),(0,"")) : repeat ((big,undefined),(big,undefined))
          d ((a,p2),(b,p5)) (c,d) = ((a+c,'D':p2),(b+d,'D':p5))
          r ((a,p2),(b,p5)) ((c,d),((e,p2'),(f,p5'))) = (s,s)
              where s = ((g,p2''),(h,p5''))
                    (g,p2'') = if a+c <= e then (a+c,'R':p2) else (e,p2')
                    (h,p5'') = if b+d <= f then (b+d,'R':p5) else (f,p5'')
          p (h:t) = (snd h) : snd (mapAccumL r (snd h) t)
          l a b = p $ zip b $ zipWith d a b
          (z,t) = uncurry min $ last $ foldl' l i $ map (map factor) ls

factor n = (m2,m5)
    where (m2,r) = f 2 n
          (m5,_) = f 5 r
          f b n = go n 0
              where go n a | r == 0    = go q $! a+1
                           | otherwise = (a,n)
                        where (q,r) = n `divMod` b

{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE BangPatterns #-}
module Main where

import Data.List (foldl')

import Data.Array (listArray, elems)

import Control.Monad (forM_, replicateM)
import Data.Functor ((<&>))
import Data.Semigroup (Sum(..))
import Data.Ord (comparing)
import Data.Word
import GHC.List (scanl')

type V = Int

badInput :: [[V]]
badInput = replicate 1000 $ replicate 1000 1

main :: IO ()
main = do
  Answer w p <- solve <$> pure badInput
  print (unWeight w)
  putStrLn (reverse p)

readInput :: IO [[V]]
readInput = do
  n <- readLn
  replicateM n $ getLine <&> map read . words

solve :: [[V]] -> Answer
solve rows = min a2 a5
  where
    a2 = findAnswer (Factor 2) rows
    a5 = findAnswer (Factor 5) rows

findAnswer :: Factor -> [[V]] -> Answer
findAnswer p (row:rows) = last $ foldl' (nextRow p) (firstRow p row) rows

firstRow :: Factor -> [V] -> [Answer]
firstRow p (first:rest) = scanl step initial rest
  where
    initial = Answer (toWeight p first) ""
    step a v = moveRight a (toWeight p v)

nextRow :: Factor -> [Answer] -> [V] -> [Answer]
nextRow p (firstUp:restUp) (first:rest) = scanl' step initial (zip restUp rest)
  where
    initial = moveDown firstUp $ toWeight p first
    step !left (up, v)  = let w = toWeight p v
     in min (moveRight left w) (moveDown up w)

moveRight :: Answer -> Weight -> Answer
moveRight (Answer w1 p) w2 = Answer (w1 <> w2) ('R':p)

moveDown :: Answer -> Weight -> Answer
moveDown (Answer w1 p) w2 = Answer (w1 <> w2) ('D':p)

toWeight :: Factor -> V -> Weight
toWeight _ 0 = Zeroed
toWeight p k = Amount (count p k)

unWeight :: Weight -> V
unWeight Zeroed = 1
unWeight (Amount a) = unCounted a

count :: Factor -> V -> Counted
count (Factor d) value = countD0 value 0
  where
    countD0 value acc = let (q, r) = quotRem value d
     in if r == 0 then countD0 q (acc + 1) else Counted acc

newtype Size = Size { unSize :: V } deriving (Show)
newtype Factor = Factor V
newtype Counted = Counted { unCounted :: V }
 deriving (Show, Eq, Ord)
 deriving Semigroup via (Sum V)

data Weight = Zeroed | Amount !Counted
  deriving (Show, Eq)

instance Ord Weight where
  compare a b = compare (unWeight a) (unWeight b)

instance Semigroup Weight where
  Zeroed <> _ = Zeroed
  _ <> Zeroed = Zeroed
  (Amount a) <> (Amount b) = Amount (a <> b)

data Answer = Answer { weight :: !Weight
                     , path :: String
                     } deriving (Show)

instance Eq Answer where
  a == b = weight a == weight b

instance Ord Answer where
  compare = comparing weight

{-# LANGUAGE BangPatterns #-}
module Main where

import qualified Data.Array.MArray.Safe as MA
import qualified Data.Array.IO.Safe as IA
import qualified Data.Array as A
import Data.Array ((!))
import Data.Int
import Control.Monad

type V = Int64
type I = Int
type Matrix = A.Array I (A.Array I V)
type Arr = IA.IOArray I
type D = Arr (Arr Solution)

readMatrix :: Int -> [String] -> Matrix
readMatrix n = A.listArray (1, n) . map (A.listArray (1, n) . fmap read . words)

data Solution = Solution {
  result :: V,
  path :: String
} deriving (Show)

countZeros :: V -> Int
countZeros value = countZeros0 value 0
  where
    countZeros0 !value !acc = let (q, r) = quotRem value 10
     in if r == 0 then countZeros0 q (acc + 1) else acc

initD :: Matrix -> IO D
initD m = do
    result <- MA.newArray_ bounds :: IO D
    forM_ [from .. to] $ \i -> MA.newArray_ bounds >>= MA.writeArray result i
    return result
  where
    bounds@(from, to) = A.bounds m

writeV :: D -> I -> I -> Solution -> IO ()
writeV m i j e = MA.readArray m i >>= \a -> MA.writeArray a j e

readV :: D -> I -> I -> IO Solution
readV m i j = MA.readArray m i >>= \a -> MA.readArray a j

debug :: D -> I -> I -> IO ()
debug m i j = do
    s <- readV m i j
    putStrLn $ show i <> " " <> show j <> " " <> show s

solve :: Matrix -> IO Solution
solve m = do
    arr <- initD m
    writeV arr 1 1 $ Solution (m ! 1 ! 1) ""
    forM_ [2 .. n] $ \i -> do
      Solution cr cp <- readV arr 1 (i - 1)
      Solution rr rp <- readV arr (i - 1) 1
      writeV arr 1 i $ Solution (cr * m ! 1 ! i) ('R':cp)
      writeV arr i 1 $ Solution (rr * m ! i ! 1) ('D':rp)
      -- debug arr 1 i
      -- debug arr i 1
    forM_ [(i, j) | i <- [2..n], j <- [2..n]] $ \(i, j) -> do
      Solution cr cp <- readV arr (i - 1) j
      Solution rr rp <- readV arr i (j - 1)
      let curV = m ! i ! j
          downR = cr * curV
          rightR = rr * curV
          res = if countZeros downR < countZeros rightR then Solution downR ('D':cp) else Solution rightR ('R':rp)
        in writeV arr i j res
      -- debug arr i j
    readV arr n n
  where
    n = length m

main :: IO ()
main = do
  n <- read `fmap` getLine :: IO Int
  m <- readMatrix n `fmap` replicateM n getLine
  res <- solve m
  print . countZeros $ result res
  putStrLn . reverse $ path res

module Main where

import Control.Applicative ((<$>))
import Data.List (foldl')

powerOf :: Int -> Int -> Int
powerOf p n = case n `mod` p of
  0 -> 1 + powerOf p (n `div` p)
  _ -> 0

data DP = DP { minNum :: !Int
             , go :: !String }
             deriving (Show)

dp :: [[Int]] -> DP
dp (row:rows) = last $ foldl' dpRow (dpFirstRow row) rows

dpRow :: [DP] -> [Int] -> [DP]
dpRow (up:ups) (cur:curs) = scanl step dpInit $ zip ups curs where
  step (DP leftNum leftGo) (DP upNum upGo, n)
    | upNum < leftNum = DP (n + upNum)   ('D':upGo)
    | otherwise       = DP (n + leftNum) ('R':leftGo)
  dpInit = DP (cur + minNum up) ('D':go up)

dpFirstRow :: [Int] -> [DP]
dpFirstRow currs = zipWith DP sums rs where
  sums = scanl1 (+) currs
  rs = iterate ('R':) []

inputGrids :: IO [[(Int, Int)]]
inputGrids = do
  n <- readLn :: IO Int
  let getPowers a = (powerOf 2 a, powerOf 5 a)
  input <- getContents
  return $ map (map getPowers . map read . words) (lines input)

main :: IO ()
main = do
  (grids2, grids5) <- unzip . map unzip <$> inputGrids
  let DP min2 go2 = dp grids2
      DP min5 go5 = dp grids5
  if min2 <= min5
    then print min2 >> putStrLn go2
    else print min5 >> putStrLn go5

module Main where

import qualified Data.Array.IArray as I
import qualified Data.Array as A
import Data.Array.Unboxed
import Data.Maybe (maybe)
import Data.List (foldl')
import qualified Data.ByteString.Char8 as C

import Debug.Trace

powerOf :: Int -> Int -> Int
powerOf p n = case n `mod` p of
  0 -> 1 + powerOf p (n `div` p)
  _ -> 0

data DP = DP { minNum :: !Int
             , go :: !String }
             deriving (Show)

dp :: Int -> Int -> [UArray Int Int] -> DP
dp n p (row:rows) = (foldl' (dpRow n p) (dpFirstRow n p (I.elems row)) rows)!(n-1)

dpRow :: Int -> Int -> A.Array Int DP -> UArray Int Int -> A.Array Int DP
dpRow n p ups curs = I.listArray (0,n-1) $ scanl step dpInit [1..n-1] where
  step (DP leftNum leftGo) n
    | upNum < leftNum = DP (powerOf p (curs!n) + upNum)   ('D':upGo)
    | otherwise       = DP (powerOf p (curs!n) + leftNum) ('R':leftGo)
    where DP upNum upGo = ups!n
  dpInit = DP (powerOf p (curs!0) + minNum up) ('D':go up)
  up = ups!0

dpFirstRow :: Int -> Int -> [Int] -> A.Array Int DP
dpFirstRow n p currs = I.listArray (0, n-1) $ zipWith DP sums rs where
  sums = scanl1 ((+) . powerOf p) currs
  rs = iterate ('R':) []

inputGrids :: IO (Int, [UArray Int Int])
inputGrids = do
  n <- readLn
  grids <- sequence $ replicate n $ do
    line <- C.getLine
    let ns = map (maybe (error "Read") fst) . map C.readInt . C.words $ line
    return $! I.listArray (0, n-1) ns
  return (n, grids)

main :: IO ()
main = do
  (n, grids) <- inputGrids
  let DP min2 go2 = dp n 2 grids
      DP min5 go5 = dp n 5 grids
  if min2 <= min5
    then print min2 >> putStrLn (reverse go2)
    else print min5 >> putStrLn (reverse go5)

import Data.List
import Data.Maybe (maybeToList)
import Data.Functor ((<$>))
import Data.Function (on)
import qualified Data.Array as A
import qualified Data.Array.Unboxed as U
import qualified Data.ByteString.Char8 as B

getPows :: Int -> Int -> Int
getPows b x = case x `divMod` b of
  (x', 0) -> 1 + getPows b x'
  _ -> 0

solve :: Int -> U.Array (Int, Int) Int -> (Int, String)
solve n mat = dp A.! (0, 0)
  where dp = A.array ((0, 0), (n-1, n-1)) [((i, j), f i j) | i <- [0..n-1], j <- [0..n-1]]
        f i j
          | i == n-1 && j == n-1 = (0, "")
          | i == n-1 = dpath
          | j == n-1 = rpath
          | otherwise = minimumBy (compare `on` fst) [dpath, rpath]
          where gridWeight = mat U.! (i, j)

                (dweight', dpath') = dp A.! (i, j+1)
                dpath = (gridWeight + dweight', 'D' : dpath')

                (rweight', rpath') = dp A.! (i+1, j)
                rpath = (gridWeight + rweight', 'R' : rpath')

main :: IO ()
main = do
  n : mat' <- map (maybe 0 fst . B.readInt) . B.words <$> B.getContents

  let mat = U.listArray ((0, 0), (n-1, n-1)) (map (\x -> if x == 0 then 10 else x) mat')

      mat2 = U.amap (getPows 2) mat
      mat5 = U.amap (getPows 5) mat

      zeroPath idx = (1, replicate x 'R' ++ replicate n 'D' ++ replicate (n-x) 'R')
        where x = idx `div` n
      cands = [solve n mat2, solve n mat5] ++ maybeToList (zeroPath <$> elemIndex 0 mat')

      (ansWeight, ansPath) = minimumBy (compare `on` fst) cands

  print ansWeight
  putStrLn ansPath

import Data.List
import Data.Maybe (maybeToList)
import Data.Functor ((<$>))
import Data.Function (on)
import qualified Data.Array.Unboxed as U
import qualified Data.ByteString.Char8 as B

getPows :: Int -> Int -> Int
getPows b =
  let getPows' b' callback acc x = case x `divMod` b' of
        (x', 0) -> getPows' b' callback (acc + 1) x'
        _ -> callback acc x
  in getPows' (b ^ 5) (getPows' b const . (* 5)) 0

solve :: Int -> U.UArray (Int, Int) Int -> Int -> (Int, String)
solve n mat b = foldl' seq n [f i j | i <- steps, j <- steps]
                `seq` (dp U.! (0, 0), findPath 0 0)

  where step = min (n `div` 2) 30
        steps = reverse [0, step .. n-1]

        getPow = getPows n

        dp :: U.Array (Int, Int) Int
        dp = U.listArray ((0, 0), (n-1, n-1)) [f i j | i <- [0..n-1], j <- [0..n-1]]

        findPath i j
          | i == n-1 = replicate (n-j-1) 'R'
          | j == n-1 = replicate (n-i-1) 'D'
          | otherwise =
            if dp U.! (i, j+1) > dp U.! (i+1, j)
            then 'D' : findPath (i+1) j
            else 'R' : findPath i (j+1)

        f i j
          | i == n-1 && j == n-1 = gridWeight
          | i == n-1 = rpath
          | j == n-1 = dpath
          | otherwise = min dpath rpath
          where gridWeight = getPow $ mat U.! (i, j)
                dpath = dp U.! (i+1, j) + gridWeight
                rpath = dp U.! (i, j+1) + gridWeight

readInt :: B.ByteString -> Int
readInt' word = case B.readInt word of
  Just (num, _) -> num
  Nothing -> 0
readInt = maybe 0 fst . B.readInt

readInput :: IO (Int, U.UArray (Int, Int) Int, [(Int, String)])
readInput = do
  n : mat' <- map readInt . B.words <$> B.getContents
  let zeroPath idx = (1, replicate x 'R' ++ replicate (n-1) 'D' ++ replicate (n-1-x) 'R')
        where x = idx `mod` n
      maybeZeroPath = maybeToList $ zeroPath <$> elemIndex 0 mat'

      mat = U.listArray ((0, 0), (n-1, n-1)) (map (\x -> if x == 0 then 10 else x) mat')
  return (n, mat, maybeZeroPath)

main :: IO ()
main = do
  (n, mat, maybeZeroPath) <- readInput

  let ans2 = solve n mat 2
      ans5 = solve n mat 5
      cands = maybeZeroPath ++ [ans2, ans5]
      (ansWeight, ansPath) = minimumBy (compare `on` fst) cands

  print ansWeight
  putStrLn ansPath

import Data.List
import Data.Maybe (maybeToList)
import Data.Functor ((<$>))
import Data.Function (on)
import qualified Data.Array as A
import qualified Data.Array.Unboxed as U
import qualified Data.ByteString.Char8 as B

getPows :: Int -> Int -> Int
getPows b x = case x `divMod` b of
  (x', 0) -> 1 + getPows b x'
  _ -> 0

solve :: Int -> U.Array (Int, Int) Int -> (Int, String)
solve n mat = dp A.! (0, 0)
  where dp = A.array ((0, 0), (n-1, n-1)) [((i, j), f i j) | i <- [0..n-1], j <- [0..n-1]]
        f i j
          | i == n-1 && j == n-1 = (0, "")
          | i == n-1 = rpath
          | j == n-1 = dpath
          | otherwise = minimumBy (compare `on` fst) [dpath, rpath]
          where gridWeight = mat U.! (i, j)

                (dweight', dpath') = dp A.! (i+1, j)
                dpath = (gridWeight + dweight', 'D' : dpath')

                (rweight', rpath') = dp A.! (i, j+1)
                rpath = (gridWeight + rweight', 'R' : rpath')

main :: IO ()
main = do
  n : mat' <- map (maybe 0 fst . B.readInt) . B.words <$> B.getContents

  let mat = U.listArray ((0, 0), (n-1, n-1)) (map (\x -> if x == 0 then 10 else x) mat')

      mat2 = U.amap (getPows 2) mat
      mat5 = U.amap (getPows 5) mat

      zeroPath idx = (1, replicate x 'R' ++ replicate n 'D' ++ replicate (n-x) 'R')
        where x = idx `mod` n
      cands = [solve n mat2, solve n mat5] ++ maybeToList (zeroPath <$> elemIndex 0 mat')

      (ansWeight, ansPath) = minimumBy (compare `on` fst) cands

  print ansWeight
  putStrLn ansPath