Given coin denominations, make a target amount. Three distinct questions, three different recurrences — mixing them up is the most common error in this family.

1. Minimum number of coins

vector<int> dp(W + 1, INT_MAX);
dp[0] = 0;
for (int w = 1; w <= W; w++)
    for (int c : coins)
        if (c <= w && dp[w - c] != INT_MAX)
            dp[w] = min(dp[w], dp[w - c] + 1);

. Order of the loops does not matter here.

2. Number of combinations (order does not matter)

Coins on the outside, amount on the inside:

vector<long long> dp(W + 1, 0);
dp[0] = 1;
for (int c : coins)                          // coin loop OUTSIDE
    for (int w = c; w <= W; w++)
        dp[w] += dp[w - c];

Each coin type is fully processed before the next, so and are never both counted.

3. Number of permutations (order matters)

Amount on the outside, coins on the inside:

vector<long long> dp(W + 1, 0);
dp[0] = 1;
for (int w = 1; w <= W; w++)                 // amount loop OUTSIDE
    for (int c : coins)
        if (c <= w) dp[w] += dp[w - c];

The loop order is the semantics

Identical bodies, swapped loops, completely different answers. For target 3 with coins : combinations gives 2 (, ); permutations gives 3 (, , ). Read the statement carefully.

When greedy works

Greedy (always take the largest coin that fits) is not generally optimal: with coins and target 6, greedy gives coins but the optimum is .

A coin system where greedy is always optimal is called canonical. Real currencies (including all common ones) are canonical, which is why the wrong intuition persists. Deciding whether a system is canonical is itself an interesting problem — Pearson’s algorithm does it in by checking a bounded set of counterexample candidates.

Never assume greedy unless the problem states the denominations and you have verified them.

The variants

QuestionRecurrence
Minimum coins
Number of combinationscoins outside, dp[w] += dp[w-c]
Number of permutationsamount outside
Is amount reachable?boolean; use a bitset for
Each coin used at most once0/1 knapsack — weight loop downward
Each coin used at most timesbounded knapsack — binary splitting or monotone queue
Maximum coins with a value limitknapsack with values
Which coins were usedstore a from[w] array and walk back
Huge , small coinsmatrix exponentiation on the linear recurrence, or the Chicken McNugget / Frobenius structure
Count solutions modulo same DP, take everything mod

The Frobenius / Chicken McNugget number

With two coprime coins , the largest amount not representable is

and exactly amounts are unrepresentable. For three or more coins there is no closed form, and computing the Frobenius number is NP-hard in general — though for small coin values a shortest-path formulation works:

Build a graph on residues mod ; edge from to with weight . The shortest distance to residue is the smallest representable amount congruent to . This “coin graph” / Dijkstra on residues technique answers “is representable” for up to in .

That trick is genuinely useful and worth remembering: when the target is astronomically large but the smallest coin is small, work modulo the smallest coin.

See also: Knapsack · Partition Problems · Generating Functions