简化问题:忘记 2 的倍数
首先,让我们先简化一下您的问题。忘掉 2 的倍数吧。假设您想要拆分一个非必然偶数n
into k
非必然均匀的部分。
显然,最平衡的解决方案是让某些部分成为n // k
,有些部分是n // k + 1
.
其中有多少个?我们打电话吧r
零件数量n // k + 1
。然后还有k - r
零件与n // k
,所有部分的总和为:
(n // k) * (k - r) + (n // k + 1) * r
== (n // k) * (k - r) + (n // k) * r + r
== (n // k) * (k - r + r) + r
== (n // k) * k + r
但这些部分应该总结为n
,所以我们需要找到r
这样:
n == (n // k) * k + r
令人高兴的是,您可能会在这里认识到欧几里得除法,n // k
是商和r
是余数。
这给了我们我们的split
功能:
def split(n, k):
d,r = divmod(n, k)
return [d+1]*r + [d]*(k-r)
Testing:
print( split(50, 3) )
# [17, 17, 16]
分成2的倍数
现在回到你的split_even
问题。现在我们有了通用函数split
, 一个简单的方法可以解决split_even
是使用split
:
def split_even(n, k):
return [2 * x for x in split(n // 2, k)]
Testing:
print( split_even(100, 3) )
# [34, 34, 32]
概括: 的倍数m
对一个数字的倍数做同样的事情很简单m
2 以外:
def split_multiples(n, k, m=2):
return [m * x for x in split(n // m, k)]
Testing:
print( split_multiples(102, 4, 3) )
# [27, 27, 24, 24]