Coin Combinations (Count Ways)

Concept

Given coin denominations and a target amount, count the number of ways to make that amount. Bottom-up DP builds from amount 0 upward. For each amount i, sum up dp[i-c] for every coin c that fits. Use modular arithmetic to handle large answers.

When to Use

  • Counting ways to make change (order matters = permutations)
  • Counting paths with different step sizes
  • Problems asking 'how many ways to reach amount X'

Intuition

dp[0] = 1 (one way to make 0: use nothing). For amount i, you could have arrived by using any coin c where c <= i. The number of ways to reach i via coin c is dp[i-c]. Sum over all coins. This counts ordered combinations (using coin 1 then coin 3 is different from coin 3 then coin 1). It's like counting paths on a number line where you can jump by any coin value.

Complexity

Time
O(amount * n)
Space
O(amount)

Template Code

cpp
#include<bits/stdc++.h>
using namespace std;

const int inf = 1e9+7;

int main(){
    ios_base::sync_with_stdio(0), cin.tie(0);
    size_t n, amount;
    cin >> n >> amount;

    vector<int> coins(n);
    for(size_t i = 0; i < n; i++) cin >> coins[i];

    vector<long long> dp(amount+1, 0);
    dp[0] = 1;

    for(int i = 1; i <= amount; i++){
        int cnt = 0;
        for(int c : coins){
            if(i - c >= 0){
                cnt += dp[i-c];
                cnt %= inf;
            }
        }
        dp[i] = cnt % inf;
    }

    cout << dp[amount];
    return 0;
}

// Sample Input:
// 3 9
// 2 3 5
//
// Sample Output:
// 8