https://www.codewars.com/kata/55aa075506463dac6600010d/haskell
题目
42的因数有:1,2,3,6,7,14,21,42
,平方后为1,4,9,36,49,196,441,1764
,和为2500,是一个完全平方数(
50×50
)。
给定两个整数
m,n(1≤m≤n)
,找出
[m,n]
中所有因数平方和为完全平方数的数(比如42)。
结果是数对的列表,数对的第一个元素是符合条件的数,第二个元素为该数的因数平方和。
样例
list_squared 1 250 = [(1, 1), (42, 2500), (246, 84100)]
list_squared 42 250 = [(42, 2500), (246, 84100)]
题解
- 暴力法(C语言风格版。。一堆递归代替循环)
module Codewars.G964.Sumdivsq where
listSquared :: Int -> Int -> [(Int, Int)]
check :: Int -> [(Int, Int)]
square d x
| d * d == x = d ^ 2
| d * d > x = 0
| x `mod` d == 0 = square (d + 1) x + d ^ 2 + div x d ^ 2
| otherwise = square (d + 1) x
check x
| floor (sqrt $ fromIntegral s) ^ 2 == s = [(x, s)]
| otherwise = []
where s = square 1 x
listSquared m n
| m > n = []
| otherwise = (check m) ++ listSquared (m + 1) n
- 暴力法(改进版,map filter用起来)
module Codewars.G964.Sumdivsq where
listSquared :: Int -> Int -> [(Int, Int)]
check :: Int -> [(Int, Int)]
factorSum :: Int -> Int
factorSum x = sum (map (^ 2) (filter ((==0) . mod x) ([1..floor (sqrt (fromIntegral x))] >>= \k -> if k * k == x then [k] else [k, div x k])))
check x
| floor (sqrt $ fromIntegral s) ^ 2 == s = [(x, s)]
| otherwise = []
where s = factorSum x
listSquared m n = concatMap check [m..n]
- 暴力法(改进改进版)
module Codewars.G964.Sumdivsq where
listSquared :: Int -> Int -> [(Int, Int)]
listSquared m n = filter (isSquare . snd) $ map (\x -> (x, factorSum x)) [m..n]
where
isSquare x = floor (sqrt $ fromIntegral x) ^ 2 == x
factorSum x = sum (map (^ 2) (filter ((==0) . mod x) ([1..floor (sqrt (fromIntegral x))] >>= \k -> if k * k == x then [k] else [k, div x k])))