我具有以下功能来计算列表中所有元素的LCM。是否有任何计算每个(n-1)个子集的每个LCM并将其存储在列表中的提示?
fun modulo (_,0) = 0
| modulo (0,_) = 0
| modulo (x,y) = if y > x then x else
let
fun getMod(z) = if z >= y then getMod(z-y) else z
in
getMod(x)
end
fun lcm (0,_) = 0
| lcm (_,0) = 0
| lcm (x,y) =
let
fun findLcm (base,mult,v) =
if modulo(mult,v) = 0
then mult
else findLcm(base,mult+base,v)
in
if x > y then findLcm(x,x,y) else findLcm(y,y,x)
end
fun ekp(xs) =
case xs of
[] => 1
| (x::xs') => lcm(x,ekp(xs'))
答案 0 :(得分:1)
假定“ S的(n-1)个子集”表示 {S \ {x} | x∈S} , S 的子集的集合,其中对于 S 的每个元素都删除了一个元素,您可以轻松生成 least首先通过生成集合,然后对每个子集应用最小公倍数算法,对每个子集的公倍数。
这是生成最小公倍数的较短方法:
fun gcd (a, 0) = a
| gcd (a, b) = gcd (b, a mod b)
fun lcm (a, b) = (a * b) div (gcd (a, b))
val lcm_list = foldl lcm 1
函数lcm_list
与您的函数ekp
相对应。
要获取从每个元素中删除一个元素的子集列表(假定没有重复项):
fun curry f x y = f (x, y)
fun subsets1 [] = []
| subsets1 (x::xs) = xs :: map (curry op:: x) (subsets1 xs)
并为每个子集生成最小公倍数,
- subsets1 [3,4,5];
> val it = [[4, 5], [3, 5], [3, 4]] : int list list
- map lcm_list (subsets1 [3,4,5]);
> val it = [20, 15, 12] : int list
也就是说,发现 {3,4,5} 的(n-1)个子集是 {{4,5},{3,5},{3 ,4}} ,并且每个(n-1)个子集的最小公倍数为 {lcm(4,5), lcm(3,5),lcm(3,4)} = {20,15,12} 。在这一点上,可能已经进行了一些多余的工作。对于任何更大的列表,子集集将具有大量重叠。例如,
- subsets1 [3,4,5,6,7,8];
> val it =
[ [4, 5, 6, 7, 8],
[3, 5, 6, 7, 8],
[3, 4, 6, 7, 8],
[3, 4, 5, 7, 8],
[3, 4, 5, 6, 8],
[3, 4, 5, 6, 7] ] : int list list
使用上述方法,我们将计算lcm (3, 4)
= 12倍四次,lcm (12, 5)
= 60倍三倍,依此类推。您可能会受益于applying memoization到{ {1}}函数,尽管它并不十分昂贵。