Counting Block Combinations I
A row of length n is filled with red blocks of minimum length 3 and black unit squares, subject to the constraint that any two red blocks are separated by at least one black square. For n = 7 there...
Problem Statement
This archive keeps the full statement, math, and original media on the page.
A row measuring seven units in length has red blocks with a minimum length of three units placed on it, such that any two red blocks (which are allowed to be different lengths) are separated by at least one grey square. There are exactly seventeen ways of doing this.

How many ways can a row measuring fifty units in length be filled?
Problem 114: Counting Block Combinations I
Mathematical Development
Theorem 1 (Tiling recurrence). Let denote the number of valid fillings of a row of length . Then
with the conventions and .
Proof. We condition on the status of the leftmost cell. There are two mutually exclusive and exhaustive cases.
Case 1. The leftmost cell is black. The remaining cells form an independent subproblem, contributing fillings.
Case 2. The leftmost cell begins a red block of length , where . If , a mandatory black separator follows the block, and the remaining subproblem has length , contributing fillings. If , the red block fills the entire row; the convention correctly accounts for this single filling.
Since every valid filling falls into exactly one of these cases, the recurrence follows. The base case counts the unique filling of an empty row (vacuously valid).
Lemma 1 (Prefix-sum optimization). Define . Then
with the convention that for .
Proof. Substitute in the summation of Theorem 1. As ranges from 3 to , ranges from down to :
The prefix sum satisfies , so each step of the recurrence costs amortized.
Proposition 1 (Simplified recurrence). For ,
Instead, from the prefix-sum form, one derives the -term linear recurrence:
equivalently, .
Proof. From Lemma 1, and . Subtracting:
However, this telescopes only if we note , which is a 5-term recurrence. To obtain the stated 2-term form, observe directly:
so … The cleanest formulation is the prefix-sum approach from Lemma 1, which we use in the algorithm.
Theorem 2 (Verification). .
Proof. Direct computation from the recurrence with prefix sums:
| 1 | 1 | |
| 0 | 1 | 2 |
| 1 | 1 | 3 |
| 2 | 1 | 4 |
| 3 | 2 | 6 |
| 4 | 4 | 10 |
| 5 | 7 | 17 |
| 6 | 11 | 28 |
| 7 | 17 | 45 |
At : . At : .
Editorial
We else. We enumerate the admissible parameter range, discard candidates that violate the derived bounds or arithmetic constraints, and update the final set or total whenever a candidate passes the acceptance test.
Pseudocode
f = map from integers to integers
f[-1] = 1; f[0] = 1
P = map from integers to integers
P[-1] = 1; P[0] = 2
For i from 1 to n:
If i >= 3 then
sum_term = P[i - 4] if i >= 4 else P[-1]
else:
sum_term = 0
f[i] = f[i - 1] + sum_term
P[i] = P[i - 1] + f[i]
Return f[n]
Complexity Analysis
- Time. . Each of the iterations performs work: one addition for and one for .
- Space. for storing the arrays and . This can be reduced to if only the final value is needed, by observing that depends on and the running prefix sum.
Answer
Code
Each problem page includes the exact C++ and Python source files from the local archive.
#include <bits/stdc++.h>
using namespace std;
int main() {
const int N = 50;
// f[i+1] stores f(i), so f(−1) is at index 0, f(0) at index 1, etc.
vector<long long> f(N + 2, 0);
vector<long long> P(N + 2, 0);
f[0] = 1; // f(-1)
f[1] = 1; // f(0)
P[0] = 1; // P(-1)
P[1] = 2; // P(0)
for (int n = 1; n <= N; n++) {
long long s = 0;
if (n >= 3) {
int idx = n - 4; // P(n-4), stored at P[idx+1]
if (idx >= -1) s = P[idx + 1];
}
f[n + 1] = f[n] + s;
P[n + 1] = P[n] + f[n + 1];
}
cout << f[N + 1] << endl;
return 0;
}
def solve():
N = 50
f = {-1: 1, 0: 1}
prefix = {-1: 1, 0: 2}
for n in range(1, N + 1):
p_idx = n - 4
if n >= 3:
p = prefix[p_idx] if p_idx >= -1 else prefix[-1]
else:
p = 0
f[n] = f[n - 1] + p
prefix[n] = prefix[n - 1] + f[n]
print(f[N])
solve()