The number of ways to distribute n identical balls into groups, so that each group has at least k balls?

I am trying to do this using recursion with memoization, I have identified the following basic cases.

I) when n == k there is only one group with all balls.

II), when k> n, then no groups can have at least k balls, therefore, zero.

I can’t move on from here. How can I do that?

By way of illustration, when n = 6, k = 2 (2,2,2) (4,2) (3,3) (6)

It can be formed of 4 different groups.

+4
source share
2 answers

This can be represented by a two-dimensional recursive formula described below:

T(0, k) = 1
T(n, k) = 0   n < k, n != 0
T(n, k) = T(n-k, k)                 +           T(n, k + 1)
             ^                                       ^
    There is a box with k balls,        No box with k balls, advance to next k
            put them 

T(n,k) - n, k.
, k : k ( , n-k ) ( , k+1 ).

, : T(6,2) (6 , 2 ):

T(6,2) = T(4,2) + T(6,3) 
T(4,2) = T(2,2) + T(4,3) = T(0,2) + T(2,3) + T(1,3) + T(4,4) =
       = T(0,2) + T(2,3) + T(1,3) + T(0,4) + T(4,5) = 
       =  1     +  0     +  0     +  1     +    0 
       = 2
T(6,3) = T(3,3) + T(6,4) = T(0,3) + T(3,4) + T(2,4) + T(6,5)
       = T(0,3) + T(3,4) + T(2,4) + T(1,5) + T(6,6) = 
       = T(0,3) + T(3,4) + T(2,4) + T(1,5) + T(0,6) + T(6,7) =
       =   1    +   0    +   0    +   0    + 1      + 0 
       = 2
T(6,2) = T(4,2) + T(6,3) = 2 + 2 = 4

, O(n^2) .

+3

:

b :

b = roundDown(n / k)

b .

x

:
k . (r = n - k * x) x :

total_distributions(x) = bincoefficient(x , n - k * x)

EDIT: onyl, . , :

. : d = {d1 , d2 , ... , dx}. , "" {r , 0 , ... , 0} 1s . , : {r - 1 , 1 , ... , 0}. , d1 >= d2 >= ... >= dx, . : 1 da db ( a = b - 1), da - 1 >= db + 1, , . 1s , . , r , , .

 countSequences(x)
     sequence[]
     sequence[0] = r

     sequenceCount = 1

     while true
         int i = findRightmostMoveable(sequence)

         if i == -1
             return sequenceCount

         sequence[i] -= 1
         sequence[i + 1] -= 1
         sequenceCount

findRightmostMoveable(sequence)
    for i in [length(sequence) - 1 , 0)
       if sequence[i - 1] > sequence[i] + 1
           return i - 1

return -1

findRightmostMoveable , ( ). , , , .

range(1 , roundDown(n / k)).map(b -> countSequences(b)).sum()
0

All Articles