【发布时间】:2011-06-26 18:45:11
【问题描述】:
我正在尝试在 Haskell 中解决这个problem,但超出了时间限制。我运用我所有的 Haskell 和数学技能来优化它,但一切都是徒劳的。有人可以建议我如何进一步优化此代码。序列 F_3 + F_7 + F_11 .... + F_(4n+3) = F_2n*F_(2n+1)。我使用 O(log n) 来计算斐波那契数。
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
【问题讨论】:
-
当您使用时间分析时,哪些函数占用的时间最多?book.realworldhaskell.org/read/…
-
没有人在haskell中解决过这个问题,可能这个问题太慢了。
-
也许一些记忆会有所帮助。
-
对于堆栈溢出,通常可以通过一些严格的注释来解决。
-
我认为问题不在于 Haskell,而在于 ghc-6.10,它是 SPOJ 使用的版本。我无法使用 ghc-6.12.3 复制堆栈溢出,这是我可用的最古老的 Haskell,但它比 ghc-7 慢得多。您可以尝试将 bang 模式添加到
matmul中的列表模式中,这可能是 thunk 正在建立的地方。