Teeth on the wheels
Cut a fixed number of notches across at least two lock wheels so the combinations multiply out as high as possible.
A padlock is a stack of dial wheels, and the workshop has a fixed number of notches to cut across them. How the notches are shared decides how many codes the lock has.
The problem
A combination padlock is built from a stack of wheels. Each wheel is cut with a whole number of notches, at least one, and turning the stack to any choice of notch on each wheel gives one code — so the number of distinct codes is the product of the wheel counts.
The workshop's cutter is set for notches cuts in total, and every cut must be
used. A lock needs at least two wheels to be a combination lock at all.
Choose how to split the notches across the stack so the number of codes is as
large as possible, and report that number.
Input. notches — an integer, the total notches to cut, at least 2.
Output. The largest product obtainable by writing notches as a sum of two
or more positive integers.
Example.
notches = 10 -> 36
Ten notches as 3 + 3 + 4 gives 36 codes. Five wheels of 2 give 32, two wheels
of 5 give 25, and 1 + 9 gives 9 — a one-notch wheel never has anything to say.
A second example, where the answer is smaller than the input:
notches = 3 -> 2
Three notches must be split, so the best is 1 + 2 and the lock has 2 codes,
fewer than the 3 a single uncut wheel would have offered. The two-wheel rule
bites at the bottom of the range.
Constraints.
2 <= notches <= 200
Hints
Hint 1
Decide the first wheel and the rest of the problem has the same shape with fewer notches. What are the two things the remainder can become?
Hint 2
Once the first wheel takes j notches, the remaining n - j can be left as one
wheel or split further. Those are different products, and the larger wins.
Hint 3
Build a table from 2 upward and each entry only reads entries below it — so one pass, and each entry costs a scan over its own possible first wheel.
Approach
Brute force
Enumerate every way to write notches as an ordered sum of positive parts and
multiply each out. The number of compositions of n is 2ⁿ⁻¹ — over 10⁵⁹ at
n = 200, and most of them repeat the same tail split thousands of times.
The insight
Fix the first wheel at j notches, and the rest is the same question about
n - j — with one twist: the remainder may be left whole, so the recurrence
takes max(n - j, best[n - j]).
That twist is the whole problem. best[m] is defined as the best product with
at least two wheels, so it refuses to report m itself; but once the first
wheel exists, leaving the remainder as a single wheel is legal. Taking the max
of the two covers both, and every subproblem is strictly smaller, so a table
filled upward reads only finished entries.
Algorithm
- Make a table
bestof sizenotches + 1, withbest[1] = 1. - For
totalfrom 2 up tonotches, and each first wheeljfrom 1 tototal - 1: - Score the split as
j * max(total - j, best[total - j]). - Keep the largest score as
best[total]. - Return
best[notches].
Complexity
Time O(n²) — one inner scan per table entry, 20000 steps at n = 200. Space O(n) for the table.
Solution
"""Teeth on the wheels — one-dimensional DP over the notches left to split."""
def solve(notches):
# best[m] = largest product from splitting m into TWO OR MORE wheels.
# best[1] = 1 is the harmless convention: a leftover 1 contributes a factor 1.
best = [0] * (notches + 1)
best[1] = 1
for total in range(2, notches + 1):
for first in range(1, total):
rest = total - first
# The remainder may stay one wheel, or be split again — take the better.
best[total] = max(best[total], first * max(rest, best[rest]))
return best[notches]The cases that ran
TESTS = [
((10,), 36),
((3,), 2),
((2,), 1),
((4,), 4),
((11,), 54),
((20,), 1458),
((200,), 2 * 3 ** 66),
]Pitfalls
- Writing the recurrence as
j * best[total - j]. It forces the remainder to be split again, sonotches = 4reports2 * best[2] = 2instead of 4. The remainder must be allowed to stay whole. - Seeding
best[n] = n. That lets the answer be one uncut wheel, andnotches = 3comes back as 3 — a lock with one wheel, which the brief forbids. Every entry must already assume the split has happened. - Stopping the inner scan at
total // 2without keeping themax. The split is symmetric only if both halves are scored the same way; drop themax(total - j, best[total - j])and the shortcut hides the real best.