はじめに
D問題やり方は思いついたが場合分けで手間取り提出できず。C問題までは割とスムーズに行きました。
A問題
問題文そのまま解く。
ABC421A.hs
main = do
n <- readLn :: IO Int
ss <- replicateM n getLine
[x,y] <- words <$> getLine
let z = read @Int x
let cand = ss !! (z-1)
putStrLn $ if cand == y then "Yes" else "No"
B問題
Haskellの効率の良いフィボナッチ数列を作るやり方を流用したものの、文字列の反転とかやってTLEならないかと一瞬あせった。10項目を出力すれば良いということで問題なしと判断。
ABC421B.hs
main = do
[x,y] <- readInts
let as = x : y : zipWith f as (tail as)
let ans = as !! (10-1)
print ans
f :: Int -> Int -> Int
f x y = read @Int $ reverse $ show (x+y)
C問題
例えばABABABパターンの場合、偶数位置にBが来た場合は無視して、残ったものを移動させる距離を求めて。。。などとややこしいやり方で解き始めたが、Bがあるべき場所との差を集計する方法を思いついた。
ABC421C.hs
main = do
n <- readLn :: IO Int
s <- getLine
let cand1 = sum $ zipWith (\x y -> abs (x-y)) [2,4..] $ map fst $ filter ((=='B').snd) $ zip [1..] s -- "ABABAB"
let cand2 = sum $ zipWith (\x y -> abs (x-y)) [1,3..] $ map fst $ filter ((=='B').snd) $ zip [1..] s -- "BABABA"
print $ min cand1 cand2
D問題
同じ区間ずつ移動するように区切ったのち、同調しながら移動する。移動中に交わるか計算する。同じタイミングで同じ位置に到達してその後同じ方向に進んだ場合はボーナスタイム。という方針で進めたが場合分けを力技でやったが解ききれず。
おわりに
久々にHaskellで解きやすいタイプの問題が多かった気がする。