挑选至少x球的方法数量(球是相同的)?

时间:2018-01-06 14:27:39

标签: python-2.7 permutation combinatorics discrete-mathematics combinators

总共有N个不同的球盒。有P个盒子,每个盒子包含许多球,剩下的Q盒每个都包含B个球。

给定数字X,你可以从盒子里挑选至少X球的方式总数是多少。

P + Q = N

示例:Number of P boxes=2每个包含2个球,Number of Q boxes=1包含2个球。 X=3(Given)其中x=minimum number of balls to be picked 所以,P + Q = 3(总箱数) 选择至少x即3球的方式的组合将是:

  

3的组合:(111),(210),(120),(021),(012),(201),(102)
  4的组合:(220)(202)(022)(211)(121)(112)
  组合5:(212)(122)(221)
  组合6:(222)
  总组合:17

我的方法:
我已经使用了"星和酒吧方法":

  

计算6:x + y + z = 6的组合,将其转换为(2-x)+(2-y)+(2-z)= 6,得出x + y + z = 0。登记/>   因此,6的组合变为二项式(2C2)= 1
  类似地,5的组合变为二项式(3C2)= 3
  组合4 =二项式(4C2)= 6
  3 =二项式(5C2)= 10的组合

1+3+6+10=20
but the answer should be 1+3+6+7=17

在计算3的组合时出现了边缘情况。我应该如何解决这个问题?

编辑:在Python中添加代码

global total_combinations
total_combinations=0

from math import factorial

def combinations(a):
    global total_combinations
    bars=numberofAs+numberofBs-1
    stars=a
    total_combinations+=factorial(stars+bars)/(factorial(bars)*factorial(stars))


numberofAs,numberofBs,numberofballsinA,numberofballsinB=map(int,raw_input().split())

x=int(raw_input())

operational_array=[]

for i in range(numberofAs):
    operational_array.append(numberofballsinA)

for i in range(numberofBs):
    operational_array.append(numberofballsinB)

max_x=sum(operational_array) #calculate combinations from x to max_x
k=max_x

for i in range(max_x,x-1,-1):
    k=max_x-i
    combinations(k)

print total_combinations

2 个答案:

答案 0 :(得分:1)

你可以在一个包含A球的盒子中 out 的球数是你可以将放入一个空盒容量A的球数。 已知有该问题的公式。

如果所有盒子最初都有相同数量的球(如给定的例子,其中A = B = 2), 并且这个数字等于或大于要从盒子中取出的球的总数,那么"星和条"将工作。 但是如果要移除的球的数量大于单个框中的数量,则存在迭代公式以找到可以选择球的方式的数量。 要从t每个包含k个球的框中删除m个球,

from scipy.special import comb

def combinations_with_limit(t, k, m):
    total = 0
    max_full_boxes = min(k, int(t/(m + 1)))
    for i in range(max_full_boxes + 1):
        total += int((-1)**i) * comb(k, i, exact=True) * comb(t + k - 1 - i*(m + 1), k - 1, exact=True)
    return total

这是基于公式in this math.stackexchange answer,但使用t而不是n来删除球的总数,以避免在此问题中使用N时出现混淆。 当然,您可以优化和改进此代码的样式 (例如,我不建议在生产代码中编写int((-1)**i)); 它以这种方式书写的原因是尽可能接近MSE答案的格式。

毫不奇怪,在A和B不同的情况下,我们必须更加努力。 要从t个包含p个方框的a个方框中删除总计q个球,每个包含b个球的def combinations_with_two_limits(t, p, q, a, b): total = 0 min_balls_from_p = max(0, t - q*b) max_balls_from_p = min(t, p*a) for i in range(min_balls_from_p, max_balls_from_p + 1): total += combinations_with_limit(i, p, a) * combinations_with_limit(t - i, q, b) return total 个方框

t

这里的想法是你首先决定如何将a球分成两组,一组从包含b球的方框中移除,另一组从包含combinations_with_two_limits的方框中删除{1}}球, 然后计算所有可以从这些框的子集中选择球的子集的方法。 通过回到上面引用的MSE公式的推导(通过生成函数或包含 - 排除原则)可以进一步优化代码,但我不会尝试它,除非它真的至关重要的是减少运行时间的几个百分点。

要从框中删除至少X个球,请取值的总和 tP*A + Q*B,取自X的所有整数值,包括您可以移除的最大数量的球 (Jan 26 00:00:15)。

答案 1 :(得分:0)

分为两部分,你从容量为A的P盒中选择 k 球,从容量为B的Q箱中选择 xk 球。使用星和棒的方法在每一边计算分别选择 k,xk 的方法的数量,并乘以得到总数。 (当然,考虑到只有当 k,x-k 都不超过容量A,B)时才能这样做。

不考虑k> A和x-k> B的情况,你必须实施下面的公式

enter image description here

其中将 n 项目分配到 k 的所有组合计数,不包括至少有一个bin包含多个C项目的组合。 在你的情况下,你需要使用这个公式两次,一次将 k 球分配给容量为A的P箱,一次将 x-k 球分配给容量为B的Q箱。 然后乘法应该给你正确的结果。