project euler problem 12

三角数の数列は自然数の和で表わされ、7番目の三角数は 1 + 2 + 3 + 4 + 5 + 6 + 7 = 28 である。 三角数の最初の10項は

1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...
となる。

最初の7項について、その約数を列挙すると、以下のとおり。

?1: 1

?3: 1,3

?6: 1,2,3,6

10: 1,2,5,10

15: 1,3,5,15

21: 1,3,7,21

28: 1,2,4,7,14,28

これから、7番目の三角数である28は、6個以上の約数をもつ最初の三角数であることが分る。

では、501 個以上の約数をもつ最初の三角数はいくらか。


素因数分解だ。またかよ。なぜか素数周りはいやなイメージが…がんばるか。

約数の数は素因数分解の指数+1の積で表せるので

import List
main=print$problem
problem= head  $ dropWhile (\x->snd x<501) $ map (\x->(x,divisor x)) $ trinum

trinum:: [Int]
trinum  = [div (n*(n+1)) 2|n<-[1..]]

factorize::Int -> [Int]
factorize x = f x 2 []
    where f x y xs = if x<y then xs else if mod x y==0 then f (div x y) y (y:xs) else f x (y+1) xs

divisor::Int -> Int
divisor x = foldl (\a b->a*(length b+1)) 1 $ group $ factorize x

素直に書いてみた。

$ time /usr/bin/runghc 12.hs
(76576500,576)

real:1m18.970s,user:1m18.825s,sys:0m0.140s

さすがにコンパイルしないと答えが返ってくるのが遅い。emacsでやってるメリットがないw

$ time ./a.out
(76576500,576)

real:0m4.851s,user:0m4.840s,sys:0m0.008s

5秒か、悪くない。

他の人の解法。なかなかおもしろい。
http://tsumuji.cocolog-nifty.com/tsumuji/2010/01/project-euler-2.html