Counting Capacitor Circuits
Using up to 18 unit capacitors (each of capacitance 1) connected in series and/or parallel combinations, how many distinct capacitance values can be obtained? Let D(n) be the set of distinct capaci...
Problem Statement
This archive keeps the full statement, math, and original media on the page.
An electric circuit uses exclusively identical capacitors of the same value $C$.
The capacitors can be connected in series or in parallel to form sub-units, which can then be connected in series or in parallel with other capacitors or other sub-units to form larger sub-units, and so on up to a final circuit.
Using this simple procedure and up to $n$ identical capacitors, we can make circuits having a range of different total capacitances. For example, using up to $n=3$ capacitors of $60 \mu F$ each, we can obtain the following $7$ distinct total capacitance values:

If we denote by $D(n)$ the number of distinct total capacitance values we can obtain when using up to $n$ equal-valued capacitors and the simple procedure described above, we have: $D(1)=1$, $D(2)=3$, $D(3)=7$, $\dots$
Find $D(18)$.
Reminder: When connecting capacitors $C_1, C_2$ etc in parallel, the total capacitance is $C_T = C_1 + C_2 + \cdots$,
whereas when connecting them in series, the overall capacitance is given by: $\dfrac{1}{C_T} = \dfrac{1}{C_1} + \dfrac{1}{C_2} + \cdots$
Problem 155: Counting Capacitor Circuits
Mathematical Foundation
Theorem 1 (Recursive Construction). Let be the set of distinct capacitance values achievable with exactly unit capacitors. Then and for :
Proof. Any circuit of capacitors has a top-level structure that is either a parallel or series combination of two sub-circuits. If the sub-circuits use and capacitors respectively (), then:
- Parallel: total capacitance .
- Series: total capacitance .
Since the combination is commutative ( and the harmonic formula is symmetric), we restrict to , i.e., , without loss of generality. Every achievable capacitance arises from some such decomposition (by structural induction on circuits), and conversely every value produced by the formula is achievable.
Theorem 2 (Rationality). Every element of is a positive rational number.
Proof. By induction on . Base case: . Inductive step: if , then and (since ).
Lemma 1 (Series-Parallel Duality). If , then .
Proof. By induction on circuit structure. Base: and . Inductive step: if circuit achieves capacitance and circuit achieves , then:
- Parallel of gives . Replacing with series gives .
- Series of gives .
By the inductive hypothesis, circuits achieving exist. Series of gives , which is .
Thus swapping every parallel with series and vice versa transforms to .
Lemma 2 (Representation). Each capacitance is stored as a reduced fraction with and . Two capacitances are equal iff their reduced fractions are identical.
Proof. The rational numbers form a field, and the reduced-fraction representation is canonical.
Editorial
S(1) = {1} S(n) = union over k=1..n//2 of { a+b, a*b/(a+b) : a in S(k), b in S(n-k) } C(n) = |S(1) union … union S(n)| Uses tuples (numerator, denominator) for speed instead of Fraction. We compute cumulative union.
Pseudocode
D = array of sets, indexed 1..N
D[1] = {Fraction(1, 1)}
For n from 2 to N:
D[n] = empty set
For k from 1 to n/2:
For each a in D[k]:
For each b in D[n-k]:
D[n].add(a + b) // parallel
D[n].add(a * b / (a + b)) // series
Compute cumulative union
all_values = D[1] union D[2] union ... union D[N]
Return |all_values|
Complexity Analysis
- Time: For each , we iterate over splits. For each split , we compute combinations. Let . The total work is . Empirically, grows to several hundred thousand for , making the total work on the order of set insertions. Each insertion into a hash set is amortized.
- Space: to store all sets. For , this is on the order of millions of fractions.
Answer
Code
Each problem page includes the exact C++ and Python source files from the local archive.
#include <bits/stdc++.h>
using namespace std;
/*
* Problem 155: Count distinct capacitance values using up to 18 unit capacitors.
*
* S(1) = {1}
* S(n) = union over k=1..n/2 of { a+b, ab/(a+b) : a in S(k), b in S(n-k) }
* C(n) = |S(1) union ... union S(n)|
*/
typedef pair<int, int> Frac; // (numerator, denominator), always reduced, den > 0
Frac make_frac(long long p, long long q) {
if (q < 0) { p = -p; q = -q; }
long long g = __gcd(abs(p), q);
return {(int)(p / g), (int)(q / g)};
}
int main() {
const int MAXN = 18;
vector<set<Frac>> S(MAXN + 1);
S[1].insert({1, 1});
set<Frac> all_values;
all_values.insert({1, 1});
for (int n = 2; n <= MAXN; n++) {
for (int k = 1; k * 2 <= n; k++) {
int m = n - k;
for (auto& a : S[k]) {
for (auto& b : S[m]) {
// Parallel: a + b = (a.p*b.q + b.p*a.q) / (a.q*b.q)
long long pn = (long long)a.first * b.second + (long long)b.first * a.second;
long long pd = (long long)a.second * b.second;
S[n].insert(make_frac(pn, pd));
// Series: ab/(a+b) = (a.p*b.p) / (a.p*b.q + b.p*a.q)
long long sn = (long long)a.first * b.first;
long long sd = (long long)a.first * b.second + (long long)b.first * a.second;
S[n].insert(make_frac(sn, sd));
}
}
}
for (auto& f : S[n]) {
all_values.insert(f);
}
}
printf("%d\n", (int)all_values.size());
return 0;
}
"""
Problem 155: Count distinct capacitance values using up to 18 unit capacitors.
S(1) = {1}
S(n) = union over k=1..n//2 of { a+b, a*b/(a+b) : a in S(k), b in S(n-k) }
C(n) = |S(1) union ... union S(n)|
Uses tuples (numerator, denominator) for speed instead of Fraction.
"""
from math import gcd
def make_frac(p, q):
"""Return reduced fraction as (p, q) with q > 0."""
if q < 0:
p, q = -p, -q
g = gcd(abs(p), q)
return (p // g, q // g)
def solve():
MAXN = 18
S = [set() for _ in range(MAXN + 1)]
S[1].add((1, 1))
all_values = {(1, 1)}
for n in range(2, MAXN + 1):
for k in range(1, n // 2 + 1):
m = n - k
for (ap, aq) in S[k]:
for (bp, bq) in S[m]:
# Parallel: a + b
pn = ap * bq + bp * aq
pd = aq * bq
S[n].add(make_frac(pn, pd))
# Series: ab/(a+b)
sn = ap * bp
sd = ap * bq + bp * aq
S[n].add(make_frac(sn, sd))
all_values |= S[n]
print(f"n={n}: |S(n)|={len(S[n])}, C(n)={len(all_values)}")
print(len(all_values))
solve()