rotate :: [[Int]] -> [[Int]] rotate x | (x !! 0) == [] = [] | otherwise = y : (rotate z) where y = [a | a <- [head b | b <- x]] z = [a | a <- [tail b | b <- x]] suml :: [Int] -> Int suml x | x == [] = 0 | otherwise = head x + suml (tail x) msuml :: [Int] -> Int -> Int msuml x m | m <= 0 = error "modulo is not natural" | x == [] = 0 | otherwise = (head x + (msuml (tail x) m)) `mod` m prod :: [Int] -> [Int] -> [Int] prod x y | (length x) /= (length y) = error "Error in prod" | x == [] = [] | otherwise = ((head x) * (head y)) : (prod (tail x) (tail y)) mprod :: [Int] -> [Int] -> Int -> [Int] mprod x y m | m <= 0 = error "modulo is not natural" | (length x) /= (length y) = error "Error int mprod" | x == [] = [] | otherwise = ((head x) * (head y) `mod` m) : (mprod (tail x) (tail y) m) prodsum :: [Int] -> [Int] -> Int prodsum x y = suml (prod x y) mprodsum :: [Int] -> [Int] -> Int -> Int mprodsum x y m | m <= 0 = error "modulo is not natural" | otherwise = msuml (mprod x y m) m mul :: [Int] -> [[Int]] -> [Int] mul x y | y == [] = [] | otherwise = (prodsum x (head y)) : (mul x (tail y)) mmul :: [Int] -> [[Int]] -> Int -> [Int] mmul x y m | m <= 0 = error "modulo is not natural" | y == [] = [] | otherwise = (mprodsum x (head y) m) : (mmul x (tail y) m) rotated_matpro :: [[Int]] -> [[Int]] -> [[Int]] rotated_matpro x y | x == [] = [] | otherwise = (mul (head x) y) : (rotated_matpro (tail x) y) mrotated_matpro :: [[Int]] -> [[Int]] -> Int -> [[Int]] mrotated_matpro x y m | m <= 0 = error "modulo is not natural" | x == [] = [] | otherwise = (mmul (head x) y m) : (mrotated_matpro (tail x) y m) matpro :: [[Int]] -> [[Int]] -> [[Int]] matpro x y = rotated_matpro x (rotate y) mmatpro :: [[Int]] -> [[Int]] -> Int -> [[Int]] mmatpro x y m | m <= 0 = error "modulo is not natural" | otherwise = mrotated_matpro x (rotate y) m repmatpro :: Int -> [[Int]] -> [[Int]] repmatpro n x | (length x) /= (length (x !! 0)) = error "Error : matrix is not square" | n < 0 = error "Error : negative pow" | n == 0 = [[1,0],[0,1]] | n == 1 = x | n `mod` 2 == 0 = matpro a a | n `mod` 2 == 1 = matpro x b where a = repmatpro (n `div` 2) x b = repmatpro (n - 1) x mrepmatpro :: Int -> [[Int]] -> Int -> [[Int]] mrepmatpro n x m | m <= 0 = error "modulo is not natural" | n < 0 = error "Error : negative pow" | n == 0 = [[1,0],[0,1]] | n == 1 = x | n `mod` 2 == 0 = mmatpro a a m | n `mod` 2 == 1 = mmatpro x b m where a = mrepmatpro (n `div` 2) x m b = mrepmatpro (n - 1) x m main = do [n,m] <- map read . words <$> getLine let modulo = 1000000007 let list1 = [[1,1],[1,0]] let list2 = mrepmatpro m list1 modulo let fibMinus = (list2!!1)!!1 let fibNow = (list2!!0)!!1 let fibPlus = (list2!!0)!!0 let list3 = [[1,fibNow,fibMinus],[0,fibPlus,fibNow],[0,fibNow,fibMinus]] let list4 = mrepmatpro n list3 modulo print $ (list4!!0)!!1