Stars and Bars — Practice Tasks¶
All tasks must be solved in Go, Java, and Python. Verify every answer against a brute-force enumerator for small inputs — the
k − 1exponent and the inclusion–exclusion sign are the two bugs that hide from inspection.
Beginner Tasks (5)¶
Task 1 — Non-negative solution count¶
Implement count(n, k) returning the number of non-negative integer solutions of x₁ + … + x_k = n, i.e. C(n + k − 1, k − 1), using a multiplicative loop (no factorials, no library comb).
Go¶
package main
import "fmt"
func binom(m, r int64) int64 {
// implement: C(m, r) via multiplicative loop, smaller index, exact division
return 0
}
func count(n, k int64) int64 {
// return binom(n+k-1, k-1)
return 0
}
func main() {
fmt.Println(count(5, 3)) // expected 21
}
Java¶
public class Task1 {
static long binom(long m, long r) {
// implement
return 0;
}
static long count(long n, long k) {
// return binom(n+k-1, k-1)
return 0;
}
public static void main(String[] args) {
System.out.println(count(5, 3)); // expected 21
}
}
Python¶
def binom(m, r):
# implement via multiplicative loop
return 0
def count(n, k):
return binom(n + k - 1, k - 1)
if __name__ == "__main__":
print(count(5, 3)) # expected 21
- Constraints:
0 ≤ n ≤ 60,1 ≤ k ≤ 60; result fits in 64-bit. - Expected Output:
count(5, 3) = 21,count(0, 4) = 1,count(10, 1) = 1. - Evaluation: correct formula, exact division, smaller-index optimization.
Task 2 — Positive solution count¶
Implement countPositive(n, k) returning the number of solutions with each xᵢ ≥ 1, i.e. C(n − 1, k − 1), returning 0 when n < k.
- Provide starter code in all 3 languages (reuse
binom). - Constraints:
0 ≤ n ≤ 60,1 ≤ k ≤ 60. - Expected Output:
countPositive(5, 3) = 6,countPositive(2, 3) = 0,countPositive(7, 1) = 1. - Evaluation: correct
n ≥ kguard.
Task 3 — Lower-bound substitution¶
Implement countWithLowerBounds(n, lows) where lows[i] is the minimum value of xᵢ. Subtract Σlows from n, return 0 if negative, else the non-negative count over len(lows) boxes.
- Provide starter code in all 3 languages.
- Constraints: lower bounds may be
0;n ≤ 60. - Expected Output:
countWithLowerBounds(20, [2,5,0,1]) = C(15,3) = 455;countWithLowerBounds(3, [2,2]) = 0. - Evaluation: correct substitution and negative-
nguard.
Task 4 — Brute-force enumerator (oracle)¶
Write bruteCount(n, k) that recursively enumerates all non-negative tuples summing to n across k boxes and returns the count. This is your test oracle for Tasks 1–3.
- Provide starter code in all 3 languages.
- Constraints:
n ≤ 15,k ≤ 6(exponential). - Expected Output:
bruteCount(5, 3) = 21; must equalcount(5, 3)for all smalln, k. - Evaluation: matches the closed-form count on every small input.
Task 5 — Inequality via slack variable¶
Implement countAtMost(n, k) returning the number of non-negative solutions of x₁ + … + x_k ≤ n. Add a slack box and return C(n + k, k).
- Provide starter code in all 3 languages.
- Constraints:
n ≤ 60,k ≤ 60. - Expected Output:
countAtMost(3, 2) = C(5,2) = 10; verify it equalsΣ_{m=0}^{n} count(m, k). - Evaluation: correct slack-box reduction; cross-check against the summation identity.
Intermediate Tasks (5)¶
Task 6 — Uniform upper bound via inclusion–exclusion¶
Implement countCapped(n, k, c) returning the number of solutions with each 0 ≤ xᵢ ≤ c, using the PIE sum Σ_{t} (−1)^t C(k,t) C(n − t(c+1) + k − 1, k − 1). Break the loop once the inner top goes negative.
- Provide starter code in all 3 languages (reuse
binom). - Constraints:
n ≤ 60,k ≤ 12,c ≤ 60. - Expected Output:
countCapped(10, 3, 4) = 6;countCapped(5, 3, 5) = 21(vacuous caps). - Evaluation: correct signs, early break; cross-check against
bruteCountwith caps.
Task 7 — Varied per-box caps (subset PIE)¶
Implement countCappedVaried(n, caps) using inclusion–exclusion over subsets of boxes: Σ_S (−1)^{|S|} C(n − Σ_{i∈S}(caps[i]+1) + k − 1, k − 1). Skip subsets whose forced total exceeds n.
- Provide starter code in all 3 languages.
- Constraints:
n ≤ 40,k = len(caps) ≤ 16. - Expected Output:
countCappedVaried(10, [4,4,4]) = 6;countCappedVaried(7, [3,2,5]) = 9. - Evaluation: correct subset iteration and pruning; matches uniform PIE when caps are equal.
Task 8 — Modular binomial pipeline¶
Build a Comb type that precomputes fact[] and invFact[] mod 1_000_000_007 (Fermat inverse, one exponentiation + backward pass), then answers C(m, r) mod p in O(1). Use it to compute the non-negative count mod p.
- Provide starter code in all 3 languages.
- Constraints: precompute up to
N = 2·10^6; up to10^5queries. - Expected Output:
C(7,2) mod p = 21; for largen, k(e.g.n = 10^6, k = 10^6) returns a residue inO(1)per query. - Evaluation: single Fermat power, correct backward inverse-factorial recurrence,
O(1)queries.
Task 9 — Compositions and the 2^{n−1} identity¶
Implement compositions(n, k) returning C(n − 1, k − 1) (compositions of n into exactly k positive parts) and verify Σ_{k=1}^{n} compositions(n, k) == 2^(n−1).
- Provide starter code in all 3 languages.
- Constraints:
n ≤ 60. - Expected Output:
compositions(5, 3) = 6; the sum overkequals16 = 2^4forn = 5. - Evaluation: correct positive formula and verified identity.
Task 10 — Monomial counting¶
Given degree d and number of variables v, return the number of distinct monomials of total degree exactly d, i.e. C(d + v − 1, v − 1). Also return the number of monomials of degree at most d (C(d + v, v)).
- Provide starter code in all 3 languages.
- Constraints:
d ≤ 50,v ≤ 50. - Expected Output: exactly degree
2in3variables →C(4,2) = 6; at most degree2in3variables →C(5,3) = 10. - Evaluation: both counts correct; the "at most" version uses the slack-box reduction.
Advanced Tasks (5)¶
Task 11 — Mixed lower and upper bounds¶
Implement countMixed(n, lows, caps) where box i satisfies lows[i] ≤ xᵢ ≤ caps[i]. First substitute lower bounds (shrink n, shift each cap by lows[i]), then apply varied-cap PIE on the residual problem.
- Provide starter code in all 3 languages.
- Constraints:
n ≤ 60,k ≤ 16,lows[i] ≤ caps[i]. - Expected Output:
countMixed(50, [3,0,0,0], [20,20,20,20])matches a brute-force check on a scaled-down instance. - Evaluation: correct order (substitute then PIE), cap shifting, and pruning.
Task 12 — Modular capped count (combine Tasks 6 and 8)¶
Implement countCappedMod(n, k, c) returning the uniform-cap count mod 1_000_000_007 using the precomputed factorial table. Guard against negative residues with (total − term + MOD) % MOD.
- Provide starter code in all 3 languages.
- Constraints:
n, k, cup to10^6; table sized ton + k. - Expected Output:
countCappedMod(10, 3, 4) = 6; large inputs return a correct residue. - Evaluation: no negative residues, early break, reuse of the
O(1)binomial.
Task 13 — Lucas' theorem for small primes¶
Implement binomLucas(m, r, p) computing C(m, r) mod p for a prime p that may be smaller than m, by multiplying digit-binomials over the base-p digits of m and r. Use it to compute a stars-and-bars count where n exceeds the modulus.
- Provide starter code in all 3 languages (cross-link sibling
24-lucas-theorem). - Constraints:
pprime,p ≤ 50,mup to10^9. - Expected Output:
binomLucas(10, 3, 7)equalsC(10,3) mod 7 = 120 mod 7 = 1. - Evaluation: correct base-
pdigit extraction and product; matches a big-integerC(m,r) % p.
Task 14 — Non-decreasing sequence count¶
Count strictly the number of non-decreasing sequences 1 ≤ a₁ ≤ a₂ ≤ … ≤ a_m ≤ k (a multiset of size m from k values), which equals C(m + k − 1, m). Verify by enumeration for small m, k.
- Provide starter code in all 3 languages.
- Constraints:
m ≤ 12,k ≤ 12. - Expected Output:
m = 2, k = 3→C(4,2) = 6:(1,1),(1,2),(1,3),(2,2),(2,3),(3,3). - Evaluation: correct multiset reduction; matches the enumerated list.
Task 15 — Anti-pattern detector¶
Write a function classify(itemsDistinct, boxesDistinct, weighted) that returns which counting tool applies: stars-and-bars C(n+k−1, k−1), power k^n (distinct items), integer partitions (identical boxes), or generating-functions/DP (weighted bins). Then implement the correct count for each branch for given small parameters.
- Provide starter code in all 3 languages.
- Constraints: small parameters; for the partition branch use a DP
O(n·k). - Expected Output: identical items + distinct boxes + unweighted → stars and bars; distinct items + distinct boxes →
k^n; identical items + identical boxes → partition countp(n, k). - Evaluation: correct classification and correct count per branch (the senior-level recognition skill).
Benchmark Task¶
Compare performance of the factorial-precompute pipeline across all 3 languages: build
fact[]modpup toN, then answer manyC(m, r)queries.
Go¶
package main
import (
"fmt"
"time"
)
const MOD = int64(1_000_000_007)
func main() {
sizes := []int{100000, 500000, 1000000, 2000000}
for _, N := range sizes {
start := time.Now()
fact := make([]int64, N+1)
fact[0] = 1
for i := 1; i <= N; i++ {
fact[i] = fact[i-1] * int64(i) % MOD
}
_ = fact[N]
fmt.Printf("N=%8d: %v\n", N, time.Since(start))
}
}
Java¶
public class Benchmark {
static final long MOD = 1_000_000_007L;
public static void main(String[] args) {
int[] sizes = {100_000, 500_000, 1_000_000, 2_000_000};
for (int N : sizes) {
long start = System.nanoTime();
long[] fact = new long[N + 1];
fact[0] = 1;
for (int i = 1; i <= N; i++) fact[i] = fact[i - 1] * i % MOD;
long use = fact[N];
System.out.printf("N=%8d: %.1f ms (last=%d)%n", N,
(System.nanoTime() - start) / 1e6, use);
}
}
}
Python¶
import timeit
MOD = 1_000_000_007
def build(N):
fact = [1] * (N + 1)
for i in range(1, N + 1):
fact[i] = fact[i - 1] * i % MOD
return fact
for N in [100_000, 500_000, 1_000_000, 2_000_000]:
t = timeit.timeit(lambda: build(N), number=1)
print(f"N={N:>8}: {t*1000:.1f} ms")
Testing Guidance¶
- Brute-force oracle: recursive enumeration must match every closed-form count for
n ≤ 15,k ≤ 6, with and without caps. - Symmetry check:
binom(m, r) == binom(m, m − r)for all smallm, r. - PIE sign check: the capped count must be non-negative and never exceed the uncapped count.
- Vacuous-cap check:
countCapped(n, k, c)withc ≥ nmust equalcount(n, k). - Identity check:
Σ_{k} compositions(n, k) == 2^(n−1);countAtMost(n, k) == Σ_{m≤n} count(m, k). - Modular cross-check:
countCappedMod(...) == countCapped(...) % pfor small inputs. - Cross-language determinism: Go, Java, and Python must produce identical output for shared inputs.