我一直试图在kattis问题上解决这个问题:https://open.kattis.com/problems/rijeci
我有下面的解决方案,但系统拒绝我的解决方案,因为完成更大的输入需要太长时间,我想知道是否有办法更有效地解决这个问题。请不要假设我知道某些方法,因为我刚刚开始学习haskell,以及针对此问题的函数式编程。
我的解决方案
convertString :: String -> String
convertString [] = []
convertString (x:xs)
| x == 'A' = 'B': convertString xs
| otherwise = 'B':'A':convertString xs
finalString :: String -> Integer -> String
finalString letters numOfTimes
| numOfTimes > 0 = finalString (convertString letters) (numOfTimes-1)
| otherwise = letters
getNumA :: String -> Int
getNumB :: String -> Int
getNumA = length . filter(=='A')
getNumB = length . filter(=='B')
main = do
inputLine <- getLine
let numOfTimes = read (inputLine) :: Integer
let convertedString = (finalString "A" numOfTimes)
putStrLn ((show (getNumA convertedString)) ++ " " ++(show (getNumB convertedString)))
答案 0 :(得分:1)
好的,让我们看看我们是否可以消除所有的装饰,并用原始递归来表达。我们只关心A和B的数量:它们的顺序与问题无关。此外,每次推送后A和B的数量仅取决于之前的A和B的数量。因此,让我们在步骤 n ( n )中调用A的数量,并在步骤 n 中调用B的数量 b'/ em>的(名词的)。
我们的基本情况是 a (0)= 1, b (0)= 0.
按下按钮后,前一个字符串中的每个A变为B,每个B变为BA。因此,新字符串中的每个A都是B→AB替换的结果,旧字符串的每个字母都会向新字符串添加一个B.
这意味着,当 n &gt; 0, a ( n )= b ( n -1)和 b ( n )= a ( n -1)+ b ( n - 1)。现在,对于 n &gt; 1,我们可以替换 a ( n -1)= b ( n -2)。这给了我们:
a (0)= 1, b (0)= 0
a (1)= 0, b (1)= 1
a ( n )= b ( n -1), b ( n )= b ( n -2)+ b ( n -1)| n &gt; 1
是否 b -zero的定义,然后是 b 的前两个值的总和 - 将你的任何其他数字序列都删除在编程类中遇到过?
答案 1 :(得分:0)
解决这个问题的诀窍与Haskell无关,而且与答案的格式有关。
问题的难点在于字符串的大小每次迭代大致加倍。所有'B'
s加倍"BA"
,所有'A'
s变为'B'
s,最终加倍。在内存中为大数字构建此字符串是难以处理的。要快速解决问题,您需要找到一种方法来避免在内存中构建字符串。这是可能的,因为答案不要求字符串,它只要求两个数字:字母数'A'
和字母数'B'
。
在执行任何步骤之前,字符串由1
'A'
和0
'B'
组成。你能算出第一步之后有多少'A'
和'B'
?
答案 2 :(得分:0)
问题不在Haskell中,而在于您对String
类型的处理方式。问题出在使用 String
类型。这个问题可以有效解决没有字符串。只需将K
的答案从 1 写入 10 :
K = 1: 0, 1
K = 2: 1, 1
K = 3: 1, 2
K = 4: 2, 3
K = 5: 3, 5
K = 6: 5, 8
K = 7: 8, 13
K = 8: 13, 21
K = 9: 21, 34
K = 10: 34, 55
所以答案是这个序列中的两个连续数字:
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, ...
这段数字对你来说是否熟悉? ;)
Haskell中有很多解决方案可以快速计算这个序列。
答案 3 :(得分:0)
你可以从一个更加数学的方面来思考这个问题:如果你有(As的数量,B的数量),你按下按钮,你会得到(B的数量,As的数量+ B的数量)
您可以在Haskell中将其写为:
step :: (Integer, Integer) -> (Integer,Integer)
step (a,b) = (b,b+a)
applyStep :: Int -> (Integer, Integer) -> (Integer,Integer)
applyStep 0 (a,b) = (a,b)
applyStep n (a,b) = applyStep (n-1) (step (a,b))