Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SPOJ Problem Flibonakki time limit exceed

I am trying to solve this problem in Haskell but getting time limit exceed. I applied all my Haskell and mathematical skill to optimize this but all in vain. Could some one please suggest me how to optimize this code further. The sequence F_3 + F_7 + F_11 .... + F_(4n+3) = F_2n*F_(2n+1). I used O(log n) to method to calculate the Fibonacci numbers.

import Data.List
import Data.Maybe
import qualified Data.ByteString.Lazy.Char8 as BS

matmul :: [Integer] -> [Integer] -> Integer -> [Integer]
matmul [a,b,c] [d,e,f] m = [x,y,z] where
    y = (a*e + b*f) `mod` m
    z = (b*e + c*f) `mod` m
    x = y + z


powM ::[Integer] -> Integer -> Integer -> [Integer]
powM a n m | n == 1 = a 
   | n == 2 = matmul a a m
   | even n = powM ( matmul a a m ) ( div n 2 ) m 
   | otherwise = matmul a ( powM ( matmul a a m ) ( div n 2 ) m ) m 

readInt :: BS.ByteString -> Integer
readInt  = fst.fromJust.BS.readInteger 

solve::Integer -> BS.ByteString
solve n = BS.pack.show $ mod ( c*d ) 1000000007 where 
 [c,d,_] = powM [1,1,0] ( 2*n ) 1000000007
--([_,a,_]:_) = powM [[1,2,1],[0,5,3],[0,3,2]] n 1000000007
-- f_3+f_7+f_11+f_15 = f_2n*f_(2n+1)

main = BS.interact $ BS.unlines. map ( solve.readInt ) . tail . BS.lines 
like image 511
keep_learning Avatar asked Nov 14 '22 21:11

keep_learning


1 Answers

Your solving seems to be fast enough but it seems that your main function does not print the answer after each new line. In fact it requires an extra newline to get the last answer so this can be the cause of your timeout! Here is a version that prints each answer directly after the input.

import Data.List
import Data.Maybe
import Control.Monad
import qualified Data.ByteString.Lazy.Char8 as B
import qualified Data.ByteString.Char8 as BC
import qualified Text.Show.ByteString as BS

matmul :: [Integer] -> [Integer] -> Integer -> [Integer]
matmul [a,b,c] [d,e,f] m = [x,y,z] where
    y = (a*e + b*f) `mod` m
    z = (b*e + c*f) `mod` m
    x = y + z

powM :: [Integer] -> Integer -> Integer -> [Integer]
powM a n m | n == 1 = a 
   | n == 2 = matmul a a m
   | even n = powM ( matmul a a m ) ( div n 2 ) m 
   | otherwise = matmul a ( powM ( matmul a a m ) ( div n 2 ) m ) m 

solve :: Integer -> Integer
solve n = mod ( c*d ) 1000000007 
  where 
  [c,d,_] = powM [1,1,0] ( 2*n ) 1000000007

readInteger :: B.ByteString -> Integer
readInteger  = fst . fromJust . B.readInteger

readInt :: B.ByteString -> Int
readInt = fst . fromJust . B.readInt

get :: IO B.ByteString
get = liftM (B.fromChunks . (:[])) BC.getLine

main :: IO ()
main = do
  n <- liftM readInt get
  replicateM_ n ( liftM readInteger get >>= B.putStrLn . BS.show . solve )
like image 148
HaskellElephant Avatar answered Dec 14 '22 22:12

HaskellElephant