Google Code Jam 2011 決勝 A, B やってみた。
コンテンツ
http://code.google.com/codejam/japan/contests.html
時間がとれたので、やってみた。どちらも、large通ったけど、解説読んでないから、完全に正しい保証はない(多分あってると思うけど、例外処理とか
A
予想をつけて、小さい問題サイズで正しいことを確認。直観的ではある。
import Control.Monad
import Text.Printf
import Data.List
f :: Num a => [a] -> a
f xs = sum $ zipWith (*) xs (tail xs)
g :: [a] -> [a] -> [a] -> ([a], [a])
g ls rs [] = (ls,rs)
g ls rs [x] = (x:ls,rs)
g ls rs (x:y:zs) = g (x:ls) (y:rs) zs
h :: [Integer] -> Double
h xs = (c*).fromIntegral $ f (x: reverse ls) + f (x: reverse rs) + (head ls) * (head rs)
where (x:xs') = reverse.sort $ xs
(ls,rs) = g [] [] xs'
c = (/2).sin $ 2 * pi / (fromIntegral $ length xs)
-- output and input function
main :: IO ()
main = do [t] <- getList :: IO [Int]
forM_ [1..t] $ \i -> do
_ <- getLine
xs <- getList :: IO [Integer]
printf "Case #%d: %f\n" i $ h xs
getList :: Read a => IO [a]
getList = liftM (map read.words) getLine
B
Project Eulerで似たような問題をやったことがあったので、それを思い出しながら。
配列使うのが面倒だったので、メモ化再帰。だから少し遅い。毎回素因数分解してるし。
import Control.Monad
import Text.Printf
import Data.List
import ONeillPrimes (primes)
import Data.MemoTrie
-- a^n (mod p)
powMod :: (Integral a, Integral b) => a -> b -> a -> a
powMod a n p | n == 0 = 1
| even n = powMod (mod (a*a) p) (div n 2) p
| otherwise = (a * powMod a (n-1) p)`mod` p
factors :: Integer -> [(Integer, Int)]
factors n = map (\xs -> (head xs, length xs)).group $ f n primes
where f _ [] = []
f m (p:ps) | p*p > m = [m]
| m `mod` p == 0 = p:f(div m p) (p:ps)
| otherwise = f m ps
totient :: Integer -> Integer
totient n = product [(p-1) * p ^ (k-1) | (p, k) <- factors n]
f, memoF :: Integer -> Integer -> Integer -> Integer
f x 0 m = x `mod` m
f x _ 1 = 0
f x _ 2 | odd x = 1
| even x = 0
f x n m | mod x m == 0 = 0
f x n m | x < s = f (x^x) (n-1) m
| c == 1 = 0
| otherwise = (`mod` m) $ (a ^ s * (powMod a (mod (b-s) m') c))
where a = memoF x (n-1) m
b = memoF x (n-1) m'
c = g x m
m' = totient c
s = h x (m `div` c)
memoF = memo3 f
g, h :: Integer -> Integer -> Integer
g x m = product [p ^ k | (p, k) <- factors m, mod x p /= 0]
h x c = toInteger.succ.length.takeWhile (\y -> y `mod` c /= 0) $ iterate (*x) x
-- output and input function
main :: IO ()
main = do [t] <- getList :: IO [Int]
forM_ [1..t] $ \i -> do
(x:n:m:_) <- getList :: IO [Integer]
printf "Case #%d: %d\n" i $ memoF x n m
getList :: Read a => IO [a]
getList = liftM (map read.words) getLine
作成者 Toru Mano
最終更新時刻 2023-01-01 (c70d5a1)