http://projecteuler.net/index.php?section=problems&id=22
必要な範囲の過剰数を全て求めて、それをひっくり返したものと比較しながら和があるかを調べます。
let rec pow n e = if e = 0 then 1 else n * (pow n (e - 1))
let rec calc_exp n p =
if n % p <> 0 then
(0, n)
else
let e, m = calc_exp (n / p) p
(e + 1, m)
let sieve max_n =
let a = [| 0..max_n |]
let d = Array.create (max_n + 1) 1
for p in Seq.takeWhile (fun n -> n * n <= max_n)
(Seq.filter (fun n -> d.[n] = 1) (seq { 2..max_n })) do
for n in seq { p..p..max_n } do
let e, m = calc_exp a.[n] p
a.[n] <- m
d.[n] <- d.[n] * (((pow p (e + 1)) - 1) / (p - 1))
for n in Seq.filter (fun n -> a.[n] <> 1) (seq { 2..max_n }) do
d.[n] <- d.[n] * (a.[n] + 1)
List.filter (fun n -> d.[n] > n * 2) [2..max_n]
let rec is_matched n (a : int List) (b : int List) =
if List.isEmpty a || List.isEmpty b then
false
else
let m = a.Head + b.Head
if m = n then true
else if m < n then is_matched n a.Tail b
else is_matched n a b.Tail
let L = 28123
let a = sieve L
let b = List.rev a
printfn "%d" (List.sum (List.filter
(fun n -> not (is_matched n a b)) [1..L]))