Solved Exercises on CSES Counting Towers Problems

Master CSES counting towers: dynamic programming, combinatorics, tower construction problems through these 3 detailed exercises.

Solution: Exercises 1 to 3
1 Basic Tower Construction
Exercise 1
Count the number of ways to build a tower of height n using blocks of height 1 or 2.
Definition:

Dynamic Programming: A method for solving complex problems by breaking them down into simpler subproblems.

Method:
  1. Define the recurrence relation
  2. Identify the base cases
  3. Compute the solution iteratively
Recurrence
f(n) = f(n-1) + f(n-2)
Base Cases
f(0)=1, f(1)=1
Fibonacci
f(n) = Fibonacci(n+1)
Step 1: Define the recurrence relation

For a tower of height n, we can either:

  • Place a block of height 1 on top of a tower of height n-1
  • Place a block of height 2 on top of a tower of height n-2

Therefore: f(n) = f(n-1) + f(n-2)

Step 2: Establish base cases

f(0) = 1 (empty tower has 1 way)

f(1) = 1 (only one block of height 1)

Step 3: Compute the sequence

f(2) = f(1) + f(0) = 1 + 1 = 2

f(3) = f(2) + f(1) = 2 + 1 = 3

f(4) = f(3) + f(2) = 3 + 2 = 5

f(n) = f(n-1) + f(n-2)
Final answer:

The number of ways to build a tower of height n is the (n+1)th Fibonacci number.

Applied rules:

• Recurrence relation: f(n) = f(n-1) + f(n-2)

• Base cases: f(0) = 1, f(1) = 1

• Dynamic programming: Store computed values to avoid recomputation

Tower Construction: Height 3
Ways to build height 3:
Block 1
Block 1
Block 1
OR
Block 2
Block 1
OR
Block 1
Block 2
Total: 3 ways for height 3
2 Colored Tower Problem
Exercise 2
Count the number of ways to build a tower of height n using red and blue blocks of height 1, with no two adjacent blocks of the same color.
Definition:

Constraint Satisfaction: Counting problems with specific restrictions on adjacent elements.

Recurrence
f(n) = 2 * f(n-1)
Base Case
f(1) = 2
Solution
f(n) = 2 * (2^(n-1))
Step 1: Analyze the constraint

For any position after the first, the color must be different from the previous block.

Step 2: Define state

Let r(n) = number of ways ending with red at position n

Let b(n) = number of ways ending with blue at position n

Then f(n) = r(n) + b(n)

Step 3: Establish relations

r(n) = b(n-1) (can only place red after blue)

b(n) = r(n-1) (can only place blue after red)

So f(n) = r(n) + b(n) = b(n-1) + r(n-1) = f(n-1)

Wait, this is wrong. Let's reconsider:

Actually, f(n) = r(n) + b(n) = b(n-1) + r(n-1) = f(n-1)

But each of r(n-1) and b(n-1) contributes to both r(n) and b(n)

So r(n) = b(n-1) and b(n) = r(n-1)

Thus f(n) = r(n) + b(n) = b(n-1) + r(n-1) = f(n-1)

Actually, for each valid sequence of length n-1, we can add either red or blue depending on the last color.

For each sequence ending in red, we can add blue.

For each sequence ending in blue, we can add red.

So r(n) = b(n-1) and b(n) = r(n-1).

And r(1) = 1, b(1) = 1, so f(1) = 2.

For n > 1: r(n) = b(n-1) and b(n) = r(n-1).

So r(n) + b(n) = b(n-1) + r(n-1) = f(n-1).

Wait, this is still wrong. Let's be more careful:

At position 1: we can place R or B → f(1) = 2

At position 2: if pos 1 is R, pos 2 must be B; if pos 1 is B, pos 2 must be R → f(2) = 2

At position 3: if pos 2 is R, pos 3 must be B; if pos 2 is B, pos 3 must be R → f(3) = 2

So f(n) = 2 for n ≥ 1

No, this is also wrong. Let's think differently:

Let r(n) be ways to build tower of height n ending with red.

Let b(n) be ways to build tower of height n ending with blue.

Then:

r(n) = b(n-1) (red can only follow blue)

b(n) = r(n-1) (blue can only follow red)

So r(n) + b(n) = b(n-1) + r(n-1)

With r(1) = 1, b(1) = 1

This means f(n) = f(n-1) for n > 1

So f(n) = 2 for all n ≥ 1

Actually, let's reconsider. If we have a valid sequence of length n-1, we have f(n-1) total ways.

For each of these, we can append the opposite color of the last one.

So for n ≥ 2, f(n) = f(n-1)

This means f(n) = 2 for all n ≥ 1.

Yes, this makes sense: at each position after the first, we have exactly 1 choice (opposite of previous).

So f(n) = 2 × 1^(n-1) = 2.

Step 4: Generalize

For n = 1: 2 ways (R or B)

For n = 2: 2 ways (RB or BR)

For n = 3: 2 ways (RBR or BRB)

Pattern: f(n) = 2

f(n) = 2
Final answer:

For a tower of height n with no adjacent same-colored blocks, there are 2 ways.

Applied rules:

• State tracking: Track endings with specific colors

• Constraint propagation: Next choice depends on previous choice

• Pattern recognition: Identify the emerging pattern

Colored Tower: No Adjacent Same Color
Height 3 Examples:
Red
Blue
Red
OR
Blue
Red
Blue
Only 2 valid patterns for any height: alternating colors
3 Weighted Block Tower
Exercise 3
Count the number of ways to build a tower of height n using blocks of heights 1, 2, or 3, where each block has a weight and the total weight must not exceed W.
Definition:

Bounded Knapsack Problem: A variant of dynamic programming where we count the number of ways to achieve a target with bounded resources.

State Definition
dp[i][w] = ways to reach height i with weight ≤ w
Transition
dp[i][w] = Σ dp[i-h][w-v]
Complexity
O(n × W × 3)
Step 1: Define the state

Let dp[i][w] = number of ways to build a tower of height exactly i with total weight at most w.

Step 2: Establish the recurrence

For each height i and weight limit w, we can reach this state by:

  • Adding a block of height 1 and weight v₁ to a tower of height i-1 and weight ≤ w-v₁
  • Adding a block of height 2 and weight v₂ to a tower of height i-2 and weight ≤ w-v₂
  • Adding a block of height 3 and weight v₃ to a tower of height i-3 and weight ≤ w-v₃

So: dp[i][w] = dp[i-1][w-v₁] + dp[i-2][w-v₂] + dp[i-3][w-v₃] (if valid)

Step 3: Initialize base cases

dp[0][w] = 1 for all w ≥ 0 (empty tower)

dp[i][w] = 0 if i < 0 or w < 0

Step 4: Compute the solution

Fill the DP table iteratively from smaller subproblems to larger ones.

Answer = dp[n][W]
Final answer:

The number of ways is stored in dp[n][W] after filling the table.

Applied rules:

• Multi-dimensional DP: State depends on both height and weight

• Resource constraints: Weight limit affects possible transitions

• Iterative computation: Build solution from base cases upward

Weighted Block Tower: Height 4, Weight Limit 5
Example Construction:
H:1, W:1
H:2, W:2
H:1, W:1
H:1, W:1
Total: H=4, W=5
Valid construction: height=4, weight=5 ≤ W_max
Comprehensive Summary: CSES Counting Towers
f(n) = \sum_{i=1}^{k} f(n-h_i)
General Recurrence
Key definitions:

Counting towers: Combinatorial problems that involve counting the number of ways to construct towers of a given height using specified blocks.

Dynamic programming: A method for solving complex problems by breaking them down into simpler subproblems and storing the results.

Recurrence relation: An equation that recursively defines a sequence based on one or more initial terms.

Constraint satisfaction: Problems with specific conditions that must be met in the solution.

Problem-solving strategies:
  1. Identify the recurrence: How does the solution for size n depend on smaller sizes?
  2. Determine base cases: What are the simplest inputs and their solutions?
  3. Handle constraints: Account for any limitations (weight, color, etc.)
  4. Optimize storage: Consider space complexity and optimize if needed
Tip 1: Always start by defining your state carefully (what does dp[i] or dp[i][j] represent?).
Tip 2: Look for patterns in small examples before generalizing.
Tip 3: Pay attention to base cases - they're crucial for correctness.
Tip 4: Consider modular arithmetic if the result needs to be taken modulo some number.
Common challenges: Identifying the correct recurrence relation, handling edge cases, managing time/space complexity, dealing with constraints.
Problem types: Basic counting, constrained counting, weighted counting, multi-dimensional DP problems.
Common recurrence patterns:

• Fibonacci-like: f(n) = f(n-1) + f(n-2)

• Linear: f(n) = f(n-1) + g(n)

• K-step: f(n) = f(n-1) + f(n-2) + ... + f(n-k)

• Weighted: f(n, w) = f(n-1, w-w₁) + f(n-2, w-w₂) + ...

Optimization techniques:

• Space optimization: Use only necessary dimensions

• Rolling array: Keep only the last few values needed

• Matrix exponentiation: For linear recurrences with large n

• Memoization: Store computed results to avoid recomputation

Advanced concepts:

Generating functions: Mathematical tools to encode sequences and solve recurrences.

Matrix exponentiation: Technique to compute linear recurrences efficiently.

Inclusion-exclusion: Principle for counting with overlapping constraints.

Verification techniques:
  1. Small cases: Manually verify solutions for small inputs
  2. Pattern matching: Check if the sequence matches known patterns
  3. Alternative method: Solve using a different approach to verify
  4. Boundary conditions: Ensure edge cases are handled correctly
Memory aid: "What can I add to a smaller solution to get this one?"
Quick check: Does the recurrence make logical sense for the problem?
Key insight: Counting towers problems often reduce to classic dynamic programming patterns that can be optimized using mathematical insights.
Advanced Techniques & Practice
\text{DP}[i] = \sum_{j \in \text{valid}(i)} \text{DP}[j]
General DP Formula
Extended applications:

Path counting: Counting paths in graphs with specific properties.

String matching: Counting strings that match certain patterns.

Tree structures: Counting valid configurations of tree nodes.

Game theory: Counting winning positions in combinatorial games.

Advanced strategies:
  1. State optimization: Reduce dimensions if possible
  2. Transition optimization: Use data structures to speed up transitions
  3. Mathematical optimization: Find closed-form solutions when possible
  4. Lazy evaluation: Compute values only when needed
Advanced Tip 1: Use matrix exponentiation for linear recurrences with large n.
Advanced Tip 2: Consider generating functions for complex recurrences.
Advanced Tip 3: Use the characteristic equation for linear homogeneous recurrences.
Foundation skills: Strong understanding of recursion, combinatorics, and basic DP concepts is essential.
Future connections: These techniques apply to many competitive programming problems and algorithm design.
Complexity analysis:

• Time complexity: Usually O(n) to O(n²) depending on transitions

• Space complexity: Can often be optimized from O(n) to O(1) for simple recurrences

• For multi-dimensional DP: O(n × m × ...) where each dimension represents a constraint

f(n) = a \cdot f(n-1) + b \cdot f(n-2) \Rightarrow f(n) = c_1 \cdot r_1^n + c_2 \cdot r_2^n
Linear Recurrence Solution
Final tip: Practice with diverse problems to recognize patterns quickly and build intuition for complex constraints.

Questions & Answers

Question: How do I know when to use dynamic programming versus other approaches for counting towers problems?

Answer: Use dynamic programming for counting towers problems when:

  • The problem has optimal substructure (solution to larger problem includes solutions to smaller problems)
  • The problem has overlapping subproblems (same subproblems are solved multiple times)
  • You can define a clear recurrence relation
  • The problem involves counting the number of ways to achieve something

For example, if building a tower of height n depends on the number of ways to build shorter towers, DP is likely the right approach. If the problem is about arranging items without clear dependencies, consider combinatorics formulas instead.

Question: What are some common mistakes to avoid when solving counting towers problems?

Answer: Common mistakes include:

  • Incorrectly defining the state in your DP table
  • Getting the recurrence relation wrong (missing transitions or adding invalid ones)
  • Wrong base cases that affect the entire solution
  • Integer overflow when computing large numbers
  • Not considering all constraints in the problem
  • Off-by-one errors in indexing

Always verify your recurrence with small examples, and consider using modular arithmetic if the problem asks for results modulo some number.

Question: How can I optimize the space complexity of counting towers solutions?

Answer: Space optimization techniques for counting towers include:

  1. Rolling array: For f(n) = f(n-1) + f(n-2), you only need the last two values
  2. State reduction: If the recurrence only depends on the last k values, keep only k variables
  3. Dimension elimination: If one dimension can be derived from others, eliminate it
  4. Bottom-up processing: Process in order to avoid storing unnecessary intermediate states

For example, the basic tower problem f(n) = f(n-1) + f(n-2) can be solved with just two variables instead of an array of size n, reducing space from O(n) to O(1).

)