【问题标题】:In how many ways can I distribute "n" candies to 3 children such that each gets at least 1 candy and at least 1 child should get more than others我可以通过多少种方式将“n”颗糖果分发给 3 个孩子,这样每个孩子至少得到 1 个糖果,并且至少 1 个孩子应该比其他孩子得到更多
【发布时间】:2021-08-09 10:11:06
【问题描述】:

我可以有多少种不同的方式将“n”颗糖果分发给 m = 3 个孩子,这样每个孩子至少得到 1 个糖果,并且至少 1 个孩子应该比其他孩子得到更多的糖果?

例如:糖果数量 = 6, 总方式 = 9
[1,4,1] , [1,1,4] , [4,1,1] , [1,2,3] , [1,3,2] 等等....总方式 = 9 .

我的 Python 代码:

import itertools

n = int(input())
arr = []

for i in range(1,n+1):
    for j in range(1, n+1):
        for k in range(1,n+1):
            if (i+j+k == n) and (i!=j or j!=k):
                if sorted(list(set(itertools.permutations([i,j,k],3)))) not in arr:
                    arr.append(sorted(list(set(itertools.permutations([i,j,k],3)))))

print(arr)       
arr1 = [arr[i][j] for i in range(len(arr)) for j in range(len(arr[i]))]
print(arr1)
print(len(arr1))

我自己解决了这个问题,尽管我对高级编程比较陌生,而且我知道我的代码没有经过优化。我想对其进行优化,并使用列表理解在一行中列出不同方式的列表。

我的列表理解有错误:

arr = [sorted(list(set(itertools.permutations([i,j,k],3))) if ((i+j+k == n) and (i!=j or j!=k) and sorted(list(set(itertools.permutations([i,j,k],3))))) not in arr for i in range(1,n+1) for j in range(1, n+1) for k in range(1,n+1)]

任何形式的帮助将不胜感激!

【问题讨论】:

  • edit您的问题并发布任何错误或追溯的全文
  • 您只想要方式的数量,还是想要所有排列?如果你只需要方法的数量,这真的只是一道数学题。
  • 我只想要方式的数量,但我也想知道方式。如果您知道如何计算方法的数量,那也会有所帮助!

标签: python arrays list-comprehension combinations permutation


【解决方案1】:

我建议您避免过多的嵌套条件和循环。您是否有理由希望您的答案涉及列表理解?我也喜欢使用它们,但超出了某个点,它们变得太长了,嗯……理解。这是一个替代解决方案,它使用更少的循环,避免长列表理解并且更容易阅读——至少在我看来。

In [29]: from itertools import permutations, combinations_with_replacement

In [30]: def all_valid_permutations(candies, members):
    ...:     combos = combinations_with_replacement(range(1, candies), members)
    ...:     valid_permutations = set()
    ...:     for item in combos:
    ...:         for perm in permutations(item):
    ...:             if sum(perm) == candies and len(set(perm)) >= members-1:
    ...:                 valid_permutations.add(perm)
    ...:
    ...:     return valid_permutations
    ...:

In [31]: all_valid_permutations(6, 3)
Out[31]:
{(1, 1, 4),
 (1, 2, 3),
 (1, 3, 2),
 (1, 4, 1),
 (2, 1, 3),
 (2, 3, 1),
 (3, 1, 2),
 (3, 2, 1),
 (4, 1, 1)}

如果您了解基本组合学,您可以猜出导入的函数的作用。 (或者您可以阅读docs,如果您愿意的话。)但是,如果不完全了解您的用例,我不能保证性能。这只是一个快速的解决方案,我想不到。我打赌你可以进一步优化。

【讨论】:

  • 只要我理解自己的代码,我更喜欢列表推导而不是使用循环和条件的传统逐行编码。这就是为什么我想使用列表理解在一行中找到解决方案(至少是“不同方式”的列表)。你的解决方案实际上比我的好。对我来说没有用例,因为这是在编码测试中提出的问题。谢谢你的帮助。您能告诉我如何将您的解决方案标记为“已接受”吗?上次帮我的用户给了我一个链接,让我接受他的解决方案。我自己不知道怎么做。
  • 很高兴您发现我的回答很有帮助。您应该能够在我的答案旁边看到一个灰色的勾号,当您单击它接受答案时,它应该变成绿色。
  • 啊……是的,谢谢!谢谢你再次帮助我!
【解决方案2】:

由于您只需要方法的数量而不是所有组合,因此这似乎更像是一道数学题而不是编程题。

将 n 颗糖果分发给 m 个孩子,所有孩子至少收到 1 颗糖果的方法数是 (n - 1)C(m - 1)。有关原因的详细说明,请阅读本页最后一节:https://brilliant.org/wiki/identical-objects-into-distinct-bins/#distribution-into-non-empty-bins

“至少 1 个孩子应该比其他孩子得到更多的糖果”也可以理解为“不是所有的孩子都应该有相同数量的糖果”。在这种情况下,如果糖果数量是孩子数量的倍数,我们只需从计算的方式数中减去所有孩子拥有相同数量糖果的情况。

from math import comb

n = 6
m = 3

numberOfWays = comb(n - 1, m - 1) - 1 if n % m == 0 else 0
print(numberOfWays)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-25
    • 1970-01-01
    • 2012-04-12
    • 1970-01-01
    • 2013-08-09
    • 1970-01-01
    相关资源
    最近更新 更多