Ways to Express an Integer as Sum of Powers

medium dynamic programming knapsack subset sum

Problem

Given two positive integers n and x, count the number of ways n can be written as the sum of the x-th power of unique positive integers. That is, count the sets of distinct integers [n1, …, nk] with n = n1x + … + nkx. Because the answer can be large, return it modulo 109 + 7. Constraints: 1 ≤ n ≤ 300, 1 ≤ x ≤ 5.

Inputn = 10, x = 2
Output1
The only way is 10 = 3² + 1². No other distinct squares sum to 10.

def numberOfWays(n, x):
    MOD = 10**9 + 7
    # dp[s] = ways to make sum s using x-th powers of distinct bases seen so far
    dp = [0] * (n + 1)
    dp[0] = 1                       # empty set makes sum 0
    base = 1
    while base ** x <= n:           # only bases whose power fits in n
        p = base ** x
        # 0/1 knapsack: walk sums high -> low so each base is used at most once
        for s in range(n, p - 1, -1):
            dp[s] = (dp[s] + dp[s - p]) % MOD
        base += 1
    return dp[n]
function numberOfWays(n, x) {
  const MOD = 1000000007n;
  // dp[s] = ways to make sum s using x-th powers of distinct bases seen so far
  const dp = new Array(n + 1).fill(0n);
  dp[0] = 1n;                       // empty set makes sum 0
  let base = 1;
  while (Math.pow(base, x) <= n) {  // only bases whose power fits in n
    const p = Math.pow(base, x);
    // 0/1 knapsack: walk sums high -> low so each base is used at most once
    for (let s = n; s >= p; s--) {
      dp[s] = (dp[s] + dp[s - p]) % MOD;
    }
    base++;
  }
  return Number(dp[n]);
}
int numberOfWays(int n, int x) {
    final int MOD = 1_000_000_007;
    // dp[s] = ways to make sum s using x-th powers of distinct bases seen so far
    long[] dp = new long[n + 1];
    dp[0] = 1;                       // empty set makes sum 0
    for (int base = 1; Math.pow(base, x) <= n; base++) {
        int p = (int) Math.pow(base, x);
        // 0/1 knapsack: walk sums high -> low so each base is used once
        for (int s = n; s >= p; s--) {
            dp[s] = (dp[s] + dp[s - p]) % MOD;
        }
    }
    return (int) dp[n];
}
int numberOfWays(int n, int x) {
    const long long MOD = 1000000007LL;
    // dp[s] = ways to make sum s using x-th powers of distinct bases seen so far
    vector<long long> dp(n + 1, 0);
    dp[0] = 1;                       // empty set makes sum 0
    for (int base = 1; pow(base, x) <= n; base++) {
        long long p = (long long) pow(base, x);
        // 0/1 knapsack: walk sums high -> low so each base is used once
        for (int s = n; s >= p; s--) {
            dp[s] = (dp[s] + dp[s - p]) % MOD;
        }
    }
    return (int) dp[n];
}
Time: O(n · n1/x) Space: O(n)