我可以用多少种方式将 "n" 糖果分发给 3 children,这样每人至少得到 1 糖果,并且至少 1 child 应该比其他人得到更多

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”个糖果分发给 m = 3 children,这样每个人至少得到 1 个糖果,并且至少 1 个 child 应该比其他人得到更多的糖果?

例如:糖果数量 = 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)]

如有任何帮助,我们将不胜感激!

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

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,如果您愿意的话。)不过,在不完全了解您的用例的情况下,我无法保证性能。这只是一个快速的解决方案,不在我的脑海中。我打赌你可以进一步优化它。

由于您只需要方法的数量而不是所有组合,因此这看起来更像是数学问题而不是编程问题。

分配n个糖果给m children的方法的数量,其中所有children至少得到1个糖果,就是(n - 1)C(m - 1)。有关原因的详细解释,请阅读本页最后一节:https://brilliant.org/wiki/identical-objects-into-distinct-bins/#distribution-into-non-empty-bins

“至少1个child应该比其他人得到更多的糖果”也可以理解为“并非所有child人应该有相同数量的糖果”。这样的话,我们只需要在计算的路数中减去所有children拥有相同数量糖果的情况即可,如果糖果数量是children数量的倍数.

from math import comb

n = 6
m = 3

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