CSCI 2824: Lecture 27

We have two topics left over in counting/combinatorics that we will look at over the rest of this week.

  • Recursive Counting: counting things by establishing recurrence relations (Section 5.5 of the book)

  • Solving Recurrences: some basic ideas on generating functions for solving interesting recurrences (Section 5.6 of the book).

Recursive Counting

The idea behind recursive counting is to set up a recurrence that expresses what you wish to count. This is especially useful when what we wish to count does not neatly fit into any of the categories studied thus far.


Q How many matches need to be played between n teams in a round-robin tournament?

You should know the answer to this problem by now and be able to reason it out in many different ways.


Let us look at it recursively. Let a_n be the number of matches for n teams. We know that

  • If n < 2 then a_n = 0. We need at least two teams to make it interesting!

  • Otherwise, a_2 = 1. Two teams will play exactly one match.

Can we now express a_n in terms of a_{n-1}?

Yes, we can say that with n teams, # of matches involving all n teams = # of matches involving teams 1… (n-1) + # of matches involving team n

Team n plays precisely n-1 matches (one with every other team). I.e, a_n = a_{n-1} + (n-1).

Therefore, the answer to the problem is governed by the recurrence relation:

  • a_n = a_{n-1} + (n-1) for n > 2

  • a_2 = 1.

The closed form solution is indeed {}^nC_2 = frac{n (n-1)}{2}.


Q What is the number of n permutations of n objects?

In other words, what is {}^n P_n?


Let us write a recurrence (in the spirit of this lecture). To obtain a permutation of n objects (numbered 1…n), let us do the following:

  • Take away the last object and permute the remaining objects from 1 .. (n-1).

  • After this, we can decide where to insert the last object.

Step 1 yields {}^{n-1} P_{n-1} possible permutations (we pretend not to know what it may be :-) )

Once we have fixed a permutation of the first n-1 objects, there are n possible places where the object #n can be inserted. Therefore the recurrence is

  • {}^nP_n = n * {}^{n-1} P_{n-1}

  • The base case for 1 object is very simple, {}^1 P_1 = 1.

Once again, we know by eyeballing the recurrence that {}^n P_n = n!.


How many solutions are there to the equation:

x_1 + ldots + x_n = r, mbox{where} n geq 1, r geq 0,  x_1,ldots,x_n geq 0.

Again, let us file under the category of things we already know how to solve by different methods :-)


Let T(n,r) represent the answer to this problem.

Simple cases:

  • Whenver r = 0, T(n,0) = 1 for all n. There is exactly one solution (set all x_1=x_2 = cdots = x_n = 0).

  • Whenever n=1, we have just one solution. Therefore, T(1,r) = 1 for all r.

Recurrence. We want to count the number of solutions T(n,r) for the general case where n > 1, r> 0. We have two cases:

  • Case-1: Assume x_n=0. Therefore, we can plug this in and take x_n out of the system.

    • This yields the system x_1 + cdots + x_{n-1} = r (x_n is set to zero, in other words).

  • Case-2: Set x_n geq 1. Following standard trick we saw last friday, we can write y_n +1 = x_n and remove x_n.

    • This yields the system x_1 + cdots + x_{n-1} + y_n +1 = r or alternatively x_1 + ldots + x_{n-1} + y_n = r -1 .

Any solution to the system either falls under case-1 or case-2. Therefore, we conclude that:  T(n,r) = T(n-1,r) + T(n,r-1).

Exercise Knowing secretly that T(n,r) = {}^{n+r-1}C_{r}, can we verify that the recurrence holds?


We wish to roll a dice n times to obtain a sum of k. Each roll of the dice can give us a number from 1 to 6.

Q Let D(n,k) be the number of ways to obtain a sum of k from n rolls of a dice. Write a recurrence relation for D(n,k).


Let us get rid of the base cases.

  • n=1 and k=1,...,6. With one roll of the dice there is just one way to obtain an outcome of 1,2,3,4,5, or 6.

    • D(1,k) = 1, mbox{where} 1 leq k leq 6.

  • n=1 and k > 6. Can you tell me what D(1,k) ought to be?

  • k leq 1 and n > 1. Since we cannot turn up 0, we have D(n,k) = 0 whenever k leq 1 and n > 1.

Now for the generic case. Suppose we wish to roll the dice n times and arrive at a sum of exactly k. Let us split cases on the last roll:

  • The last roll showed up 1 and first n-1 rolls sum up to k-1.

  • The last roll shows up 2 and first n-1 rolls sum up to k-2

  • cdots

  • The last roll shows up to 6 and first n-1 rolls sum up to k-6.

Therefore, can we now write a recurrence to express the sum?

D(n,k) = D(n-1, k-1) + D(n-1,k-2) + cdots + D(n-1,k-6), n > 1, k geq 6 .

A recurrence should directly allow you to write an efficient program to compute the answer using dynamic programming.


Let us take the following recurrence:

  • T(n,1) = 1 for all n > 0

  • T(1,r) = 1 for all r geq 0

  • T(n,r) = T(n-1,r) + T(n,r-1) if  r > 1 or  n > 1.

How do we solve it? We can write a program to compute T(n,r).

Program to compute T

 int T(int n, int r){
    assert( n > 1);
    assert( r > 1);
    /*-- Base Case --*/
    if ( r == 1) return 1;
    if ( n == 1) return 1;
    /* Recurrence */
    return T(n-1,r) + T(n,r-1);

I implemented this in C and ran it. Here are the running times and some results:

n r Time (sec)
10 10 < .1 s
20 10 .1 s
15 15 .4 s
17 17 6 s
18 18 24 s
19 19 92 s
20 20   6 mins

We will explain how this recurrence can be computed faster in class.