16. The sum and product rules

Combinatorics is the science of counting: computing the number of possibilities without having to list them one by one. At OSN it appears as direct math problems, and as part of programming problems whose answer is too large to compute with a loop.

Two rules are the foundation of everything.

The sum rule

If a choice can be made in a ways or in b ways, and the two groups do not overlap, then there are a + b ways in total.

The key word is or, and the condition is no overlap.

Example: on the table there are 3 kinds of cake and 4 kinds of fried snacks. If Budi takes one food item, there are 3 + 4 = 7 choices.

The product rule

If an activity consists of two steps, the first step can be done in a ways and the second step in b ways (whatever the result of the first step), then there are a × b ways in total.

The key word is and, and the condition is that the number of ways for the second step does not depend on the choice made in the first step.

Example: Budi takes one cake and one fried snack: 3 × 4 = 12 pairs.

The tree diagram shows why the results are multiplied: every first branch splits again into as many branches as there are second choices.

                 pick a cake
        /            |            \
    cake A        cake B        cake C
    / | | \      / | | \       / | | \
   g1 g2 g3 g4  g1 g2 g3 g4   g1 g2 g3 g4

There are 3 branches at the first level, each producing 4 branches, so there are 3 × 4 = 12 leaves.

The most common mistake with these two rules is not miscounting, but picking the wrong rule. One question decides it:

Am I choosing one among several groups (sum), or taking one from each group (product)?

Phrase in the problem The rule
"one food or one drink" sum
"one food and one drink" product
"may choose only A, only B, or both" sum over three separate possibilities
"length n, each position freely chosen from k letters" product n times → kⁿ
"taken one at a time without replacement" decreasing product: n × (n−1) × …

A quick way to tell them apart: draw the tree. If two groups of choices stand side by side (pick one branch), it is a sum. If one choice is followed by the next choice (go down one level), it is a product.

Combining the two

A license plate consists of one letter (A–Z) followed by three digits (0–9), and digits may repeat. How many plates are there?

26 × 10 × 10 × 10 = 26,000.

What if digits may not repeat?

26 × 10 × 9 × 8 = 18,720. After one digit is used, the next choices decrease — this is the early form of permutations (Chapter 17).

How many passwords of length 4 from lowercase letters a–z must contain at least one letter a?

Here it is easier to count the opposite:

  • all passwords: 26⁴ = 456,976
  • those that do not contain a at all: 25⁴ = 390,625
  • the answer: 456,976 − 390,625 = 66,351

This technique is called the complement, and it is used very often: counting "at least one" is almost always easier through "none at all".

The reason counting directly is harder: "at least one a" means there can be one a, two, three, or four — four groups that have to be counted and then added, and those groups easily overlap if you are not careful. Whereas "no a at all" is only one computation: every position freely chooses from 25 letters.

A small example that can be checked by hand: passwords of length 3 from the 4 letters a b c d, at least one a. In total 4³ = 64, those without a 3³ = 27, so the answer is 64 − 27 = 37. Listing all thirty-seven words directly one by one can be done, but takes much longer — and for length 10 it is already impossible.

Other forms that also use the complement:

What is asked Computed as
"at least one ..." total − "none at all"
"at least two ..." total − "none" − "exactly one"
"two of them are equal" total − "all different"
"not all of them are equal" total − "all equal"

Open exercises/16/02-komplemen.cpp. The program computes the answer above in two ways: the complement formula and direct enumeration over all 456,976 passwords. Run it and make sure both agree.

When the groups overlap

The sum rule is only valid when the two groups have no members in common. If they overlap, what is used is inclusion-exclusion:

|A ∪ B| = |A| + |B| − |A ∩ B|

Example: of the numbers 1 to 100, how many are divisible by 3 or 5?

  • divisible by 3: ⌊100/3⌋ = 33
  • divisible by 5: ⌊100/5⌋ = 20
  • divisible by 15 (both): ⌊100/15⌋ = 6
  • the answer: 33 + 20 − 6 = 47

Without subtracting the intersection, numbers like 15, 30, and 45 are counted twice.

Two things need to be understood from that computation. First, the number of numbers from 1 to n divisible by p is n / p with integer division — exactly the / operation in C++ for positive numbers, with no loop needed. Second, the intersection "divisible by 3 and divisible by 5" is not 3 × 5 in every case, but their LCM (Chapter 15). For 3 and 5 it happens to be the same because they are coprime, but for 4 and 6 the intersection is the multiples of 12, not 24.

For three sets, the pattern continues:

|A ∪ B ∪ C| = |A| + |B| + |C| − |A∩B| − |A∩C| − |B∩C| + |A∩B∩C|

The signs alternate: single terms are added, pairwise terms are subtracted, triple terms are added again. The reason can be traced on one number that is in all three sets at once: it is counted 3 times by the single terms, subtracted 3 times by the pairwise terms, then added 1 time by the triple term — a total of 1, exactly as it should be.

Example: from 1 to 100, how many are divisible by 2, 3, or 5?

50 + 33 + 20 − 16 − 10 − 6 + 3 = 74

with 16 = ⌊100/6⌋, 10 = ⌊100/10⌋, 6 = ⌊100/15⌋, and 3 = ⌊100/30⌋.

Open exercises/16/01-aturan-dasar.cpp. Add direct enumeration for that last problem — one loop from 1 to 100 with one if — then make sure the result is also 74.

Checking counts with a program

This is the habit that sets careful contestants apart: every combinatorics formula can be tested with an enumerating program for small cases.

// formula: 26 * 10 * 9 * 8
long long rumus = 26LL * 10 * 9 * 8;

// direct enumeration
long long cacah = 0;
for (int h = 0; h < 26; h++)
    for (int a = 0; a < 10; a++)
        for (int b = 0; b < 10; b++)
            for (int c = 0; c < 10; c++)
                if (a != b && a != c && b != c) cacah++;

cout << rumus << " " << cacah << "\n";   // must be equal

If the two differ, the formula is wrong — and it is better to find out now than during the contest.

Direct enumeration is only possible for small data. That is exactly the point: check the formula for n = 3, 4, 5, then use the formula for n = 10¹⁸. This way of working is exactly the same as the comparison tester in Chapter 10.

OSN problem patterns

Problem form Tool
"how many ... of length n" product rule, kⁿ
"... at least one ..." complement
"... divisible by p or q" inclusion-exclusion
"... may not repeat" decreasing product (permutation)
"order does not matter" combination (Chapter 17)
the answer is huge modulo 10⁹ + 7 (Chapter 14)

Homework

Problems 1 and 2 are worked on paper first, then checked with a program.

Problem 1 — Count on paper

Write the answer and how you computed it for:

a. How many three-digit numbers (100–999) have all even digits? b. How many three-digit numbers contain at least one digit 7? c. From 1 to 1,000, how many are divisible by 4 or 6? d. A menu has 4 foods, 3 drinks, and 2 desserts. How many different packages can be put together if a package must contain one food and one drink, while a dessert may or may not be taken?

Problem 2 — Check with a program

Open exercises/16/homework/02-periksa.cpp. For each part of problem 1, write direct enumeration with nested loops, then compare it with your paper answer. If they differ, find which one is wrong.

Problem 3 — Passwords

Open exercises/16/homework/03-sandi.cpp. Read n (≤ 10¹⁸) and k (≤ 26). Print the number of passwords of length n from the first k letters of the alphabet that contain at least one letter a, modulo 1,000,000,007. Use the complement and fast modular exponentiation from Chapter 14.

Problem 4 — Inclusion-exclusion

Open exercises/16/homework/04-inklusi.cpp. Read n, p, and q (n ≤ 10¹⁸). Print the number of numbers from 1 to n divisible by p or q. Hint: you need the LCM from Chapter 15, and watch out for overflow.

Challenge — Three sets

Open exercises/16/homework/05-tiga-himpunan.cpp. Read n, p, q, and r. Print the number of numbers from 1 to n divisible by at least one of the three. Write the seven-term inclusion-exclusion formula, then test it with direct enumeration for n ≤ 10,000.

Most common mistakes

Mistake Consequence
using the sum when the groups overlap some are counted twice
using the product when the second choice depends on the first answer too large
forgetting that choices decrease under "may not repeat" kⁿ used when it should decrease
intersection of two conditions computed as p × q wrong when p and q are not coprime; use the LCM
counting "at least one" directly the groups overlap; use the complement
product stored in an int overflow; use long long or modulo

OSN tips

Turn the problem into a single sentence "how many ways are there to choose ...". If that sentence says "then", use the product rule; if it says "or", use the sum rule. Most mistakes on combinatorics problems come from choosing wrongly between those two words.

Count by hand first for the smallest cases. For N = 1, N = 2, and N = 3, the answer can often be enumerated one by one on paper. Your formula must match on all three before it is trusted for N = 10¹⁸.

Check the formula with an enumerating program. Write a brute force that enumerates all possibilities for small N, then compare it with your formula. This is the fastest way to find a mistake that is off by a factor — and the only way that can be trusted when contest time is running out.

The complement is almost always easier than direct counting. The phrase "at least one" is the cue: count everything, then subtract those that have none. For "at least one a and at least one b", the complement is two overlapping sets, and their intersection has to be added back once — that is inclusion-exclusion.

Combinatorics answers explode, so a modulo is almost always required. Once there is a % MOD, all the habits of Chapter 14 apply: take the remainder at every step, use long long, and wrap subtractions with + MOD.

Modular subtraction without adjustment is a bug waiting to happen. The complement formula always contains a subtraction, and its intermediate result can be negative. The standard form:

hasil = ((semua - tanpa) % MOD + MOD) % MOD;

Pay attention to whether order counts. "A pair (x, y)" usually means ordered — (1, 2) and (2, 1) are different. "Choosing two people" usually does not. OSN problems state it, but the sentence is easy to miss, and the answer differs by exactly a factor of two.

The edge cases that most often break combinatorics formulas are the smallest values: N = 1, K = 1, or K = 2. The formula K × (K−1)^(N−1), for example, must still be correct for N = 1, when the exponent becomes zero. Test all three before submitting.

Summary

  • The sum rule for "or" on groups that do not overlap; the product rule for "and" in steps.
  • If the groups overlap, use inclusion-exclusion: |A ∪ B| = |A| + |B| − |A ∩ B|, with alternating signs for three or more sets.
  • The intersection "divisible by p and q" is the multiples of LCM(p, q), not always p × q.
  • "At least one" is almost always easier through the complement: the total minus "none at all".
  • The number of numbers 1 to n divisible by p is n / p with integer division.
  • Every counting formula can and should be checked with direct enumeration on small data, exactly like the comparison tester in Chapter 10.

OSN-style exercises

All three are solved with a formula, not enumeration. Before typing, work out N = 1 and N = 2 by hand, then make sure your formula matches.

The skeletons for all three are in exercises/16/osn/.

Problem 1 — Colored Flag

A flag consists of N stripes lined up from left to right. Each stripe is colored with one of the K available colors. Two adjacent stripes may not have the same color; stripes that are further apart may.

Count how many different flags can be made, then output the remainder when divided by 1,000,000,007.

Input format. One line containing two integers N and K.

Output format. One line containing the number of flags modulo 1,000,000,007.

Constraints.

  • 1 ≤ N ≤ 10¹⁸
  • 1 ≤ K ≤ 10⁹

Sample input

3 3

Sample output

12

Explanation. The first stripe may be any color: 3 choices. The second stripe may be any color except the color of the first stripe: 2 choices. The third stripe may be any color except the color of the second stripe: 2 choices. In total 3 × 2 × 2 = 12.

Note the case K = 1: the only valid flag is a flag with a single stripe.

The skeleton: exercises/16/osn/01-bendera-warna.cpp

Problem 2 — Password With Two Required Letters

A system accepts passwords of exactly N letters, and the letters that may be used are the first K letters of the alphabet. The extra rule: the password must contain at least one letter a and at least one letter b.

Count how many valid passwords there are, then output the remainder when divided by 1,000,000,007.

Input format. One line containing two integers N and K.

Output format. One line containing the number of passwords modulo 1,000,000,007.

Constraints.

  • 1 ≤ N ≤ 10¹⁸
  • 2 ≤ K ≤ 26

Sample input

2 3

Sample output

2

Explanation. The letters are a, b, and c. Of the nine two-letter words, the only ones containing both a and b are ab and ba.

The skeleton: exercises/16/osn/02-sandi-dua-huruf.cpp

Problem 3 — Pairs Summing to a Multiple of K

Count how many ordered pairs (x, y) with 1 ≤ x, y ≤ N there are such that x + y is divisible by K. The pairs (1, 2) and (2, 1) are considered different, and x may equal y.

Input format. One line containing two integers N and K.

Output format. One line containing the number of pairs.

Constraints.

  • 1 ≤ N ≤ 10⁹
  • 1 ≤ K ≤ 10⁶

Sample input

5 3

Sample output

9

Explanation. The pairs are (1,2), (2,1), (1,5), (5,1), (2,4), (4,2), (3,3), (4,5), and (5,4). Checking every pair one by one takes N² = 10¹⁸ steps, so what must be grouped is the remainders, not the numbers.

The skeleton: exercises/16/osn/03-pasangan-kelipatan.cpp

Stuck or already done? Open the homework solutions page.