Life Goes On

まあまあだけど楽しんでる方です

108問目

1/x + 1/y = 1/n を満たす x, y の組を考える。n = 4 のとき、解は (x, y) = (5, 20), (6, 12), (8, 8) の 3 組であるが、解の個数が初めて 1,000 を超えるのは n がいくつのときか。
ずいぶん前に解いたので、自分で書いたコードが読めなくなっていて、改めて書き直しました。
題意の式を変形すると (x-n)(y-n) = n2 となり、n2の約数の個数を求める問題になります。
重複を排除するので約数の個数が 2,000 以上であれば OK 。
n = 2a + 3b + 5c .. とおくと、n2 の約数は (2a+1)(2b+1)(2c+1).. なので、これが 2000 以上となるような a, b, c, .. の組を求めて、そのうち n が最小値となるものが答えです。
a の上限値の 5 がイマイチだけど、これを外すのはけっこうメンドウなのでこのまま。

main = print $ euler108 1000

euler108 :: Integer -> Integer
euler108 n = minimum $ map (product . zipWith (^) primes) $ indices (2*n) 5 1

indices :: Integer -> Integer -> Integer -> [[Integer]]
indices s0 m s
    | s > s0 = [[]]
    | otherwise = [ n:ns | n <- [1..min m mb], ns <- indices s0 n (f n) ]
    where mb = head $ dropWhile ((< s0) . f) [1..]
          f = (* s) . (+ 1) . (* 2)

primes :: [Integer]
primes = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47]