# will build list such that numTrees[n] is the number of distinct trees with n leaves
numTrees = [1,1,1]    # seed results with 1 way to trivially have a tree with 2 or less leaves

# How many ways can n things be distinctly divided into groups of size a and b (for n=a+b)
def distinctGroups(n,a,b):
    ans = 1
    for k in range(b+1,n+1):     # first compute factorial(n)/factorial(b)
        ans  = ans*k
    for k in range(1,1+a):       # now divide out factorial(a)
        ans = ans // k
    if a == b:                   # SPECIAL CASE: for equal groups divide out symmetry
        ans = ans // 2           # (i.e. doesn't matter which group is "a" and which group is "b")
    return ans
    
# compute for n=3 and onward...
for n in range(3,31):
    count = 0
    for a in range(1,1+n//2):  # a is size of the smaller group (unless a,b equal)
        b = n-a

        # determine number of ways do uniquely divide group of n into
        # two groups of a and b respectively.
        grouping = distinctGroups(n,a,b)

        # for each such grouping there are numTrees[a] ways to design
        # the subtree of size a, and numTrees[b] ways to design the
        # subtree of size b
        count += grouping * numTrees[a] * numTrees[b]


    numTrees.append(count)
    print(n, count)
