All Euler problems
Project Euler

Subsets with a Unique Sum

For any set A of numbers, let sum(A) denote the sum of the elements of A. Consider the set S = {1^2, 2^2, 3^2,..., 100^2}. Let U be the set of all integers v such that exactly one 50-element subset...

Source sync May 21, 2026
Problem #0201
Level Level 09
Solved By 2,752
Languages C++, Python
Answer 115039000
Length 384 words
dynamic_programminglinear_algebrasequence

Problem Statement

This archive keeps the full statement, math, and original media on the page.

For any set \(A\) of numbers, let \(\operatorname {sum}(A)\) be the sum of the elements of \(A\).

Consider the set \(B = \{1,3,6,8,10,11\}\).

There are \(20\) subsets of \(B\) containing three elements, and their sums are: \begin {align*} \operatorname {sum}(\{1,3,6\}) &= 10,\\ \operatorname {sum}(\{1,3,8\}) &= 12,\\ \operatorname {sum}(\{1,3,10\}) &= 14,\\ \operatorname {sum}(\{1,3,11\}) &= 15,\\ \operatorname {sum}(\{1,6,8\}) &= 15,\\ \operatorname {sum}(\{1,6,10\}) &= 17,\\ \operatorname {sum}(\{1,6,11\}) &= 18,\\ \operatorname {sum}(\{1,8,10\}) &= 19,\\ \operatorname {sum}(\{1,8,11\}) &= 20,\\ \operatorname {sum}(\{1,10,11\}) &= 22,\\ \operatorname {sum}(\{3,6,8\}) &= 17,\\ \operatorname {sum}(\{3,6,10\}) &= 19,\\ \operatorname {sum}(\{3,6,11\}) &= 20,\\ \operatorname {sum}(\{3,8,10\}) &= 21,\\ \operatorname {sum}(\{3,8,11\}) &= 22,\\ \operatorname {sum}(\{3,10,11\}) &= 24,\\ \operatorname {sum}(\{6,8,10\}) &= 24,\\ \operatorname {sum}(\{6,8,11\}) &= 25,\\ \operatorname {sum}(\{6,10,11\}) &= 27,\\ \operatorname {sum}(\{8,10,11\}) &= 29. \end {align*}

Some of these sums occur more than once, others are unique.

For a set \(A\), let \(U(A,k)\) be the set of unique sums of \(k\)-element subsets of \(A\), in our example we find \(U(B,3) = \{10,12,14,18,21,25,27,29\}\) and \(\operatorname {sum}(U(B,3)) = 156\).

Now consider the \(100\)-element set \(S = \{1^2, 2^2, \dots , 100^2\}\).

S has \(100891344545564193334812497256\) \(50\)-element subsets.

Determine the sum of all integers which are the sum of exactly one of the \(50\)-element subsets of \(S\), i.e. find \(\operatorname {sum}(U(S,50))\).

Problem 201: Subsets with a Unique Sum

Mathematical Development

Definition 1. Let S={a1,a2,…,an}S = \{a_1, a_2, \ldots, a_n\} with ai=i2a_i = i^2 and n=100n = 100. For integers 0≤j≤n0 \leq j \leq n and s≥0s \geq 0, define the subset count function

c(j,s)=∣{T⊆S:∣T∣=j and sum⁡(T)=s}∣.c(j, s) = \bigl|\bigl\{T \subseteq S : |T| = j \text{ and } \operatorname{sum}(T) = s\bigr\}\bigr|.

The problem asks for ∑v:c(50,v)=1v\sum_{v : c(50, v) = 1} v.

Theorem 1 (Sum Bounds). The sum of any 50-element subset of SS lies in the interval [Smin⁡,Smax⁡][S_{\min}, S_{\max}] where

Smin⁡=∑k=150k2=42925,Smax⁡=∑k=51100k2=295425.S_{\min} = \sum_{k=1}^{50} k^2 = 42925, \qquad S_{\max} = \sum_{k=51}^{100} k^2 = 295425.

Proof. The minimum is attained uniquely by {12,22,…,502}\{1^2, 2^2, \ldots, 50^2\} and the maximum uniquely by {512,522,…,1002}\{51^2, 52^2, \ldots, 100^2\}. Applying the identity ∑k=1mk2=m(m+1)(2m+1)/6\sum_{k=1}^{m} k^2 = m(m+1)(2m+1)/6 yields Smin⁡=50⋅51⋅101/6=42925S_{\min} = 50 \cdot 51 \cdot 101 / 6 = 42925. The total ∑k=1100k2=100⋅101⋅201/6=338350\sum_{k=1}^{100} k^2 = 100 \cdot 101 \cdot 201 / 6 = 338350, so Smax⁡=338350−42925=295425S_{\max} = 338350 - 42925 = 295425. □\square

Lemma 1 (Recurrence). The subset count function satisfies the recurrence

ci(j,s)=ci−1(j,s)+ci−1(j−1,s−ai)c_i(j, s) = c_{i-1}(j, s) + c_{i-1}(j-1, s - a_i)

for i=1,…,ni = 1, \ldots, n, with the convention c0(0,0)=1c_0(0, 0) = 1 and c0(j,s)=0c_0(j, s) = 0 otherwise. Here ci(j,s)c_i(j, s) denotes the count restricted to subsets of {a1,…,ai}\{a_1, \ldots, a_i\}.

Proof. The jj-element subsets of {a1,…,ai}\{a_1, \ldots, a_i\} summing to ss are partitioned into those not containing aia_i (counted by ci−1(j,s)c_{i-1}(j, s)) and those containing aia_i (counted by ci−1(j−1,s−ai)c_{i-1}(j-1, s - a_i)). □\square

Theorem 2 (Three-State DP Sufficiency). Define the clamped count c^i(j,s)=min⁡(ci(j,s),2)\hat{c}_i(j, s) = \min(c_i(j, s), 2). Then c^i\hat{c}_i satisfies

c^i(j,s)=min⁡(c^i−1(j,s)+c^i−1(j−1,s−ai),  2)\hat{c}_i(j, s) = \min\bigl(\hat{c}_{i-1}(j, s) + \hat{c}_{i-1}(j-1, s - a_i),\; 2\bigr)

and correctly determines whether cn(j,s)c_n(j, s) is 00, 11, or ≥2\geq 2.

Proof. We show by induction on ii that c^i(j,s)=min⁡(ci(j,s),2)\hat{c}_i(j, s) = \min(c_i(j, s), 2) for all j,sj, s.

Base case (i=0i = 0): c^0(0,0)=min⁡(1,2)=1=c0(0,0)\hat{c}_0(0, 0) = \min(1, 2) = 1 = c_0(0, 0), and all other entries are 00.

Inductive step: Assume c^i−1(j,s)=min⁡(ci−1(j,s),2)\hat{c}_{i-1}(j, s) = \min(c_{i-1}(j, s), 2) for all j,sj, s. Let u=ci−1(j,s)u = c_{i-1}(j, s) and w=ci−1(j−1,s−ai)w = c_{i-1}(j-1, s-a_i), so ci(j,s)=u+wc_i(j,s) = u + w. We must show min⁡(min⁡(u,2)+min⁡(w,2),2)=min⁡(u+w,2)\min(\min(u,2) + \min(w,2), 2) = \min(u + w, 2).

  • If u+w≤1u + w \leq 1: then u,w≤1u, w \leq 1, so min⁡(u,2)=u\min(u,2) = u and min⁡(w,2)=w\min(w,2) = w, giving min⁡(u+w,2)=u+w\min(u + w, 2) = u + w.
  • If u+w≥2u + w \geq 2: then min⁡(u,2)+min⁡(w,2)≥min⁡(u+w,4)≥2\min(u,2) + \min(w,2) \geq \min(u + w, 4) \geq 2, so the clamp yields 22. □\square

Corollary. The set U={v:c^n(50,v)=1}U = \{v : \hat{c}_n(50, v) = 1\} is precisely the set of sums achieved by exactly one 50-element subset.

Editorial

The key observation is that we never need the exact number of subsets once that number reaches 2. For each subset size and each possible sum, it is enough to remember whether the sum is unreachable, achievable in exactly one way, or achievable in at least two ways. That turns the problem into a 0/1 knapsack-style dynamic program with a three-state counter instead of an unbounded integer counter.

We process the squares in increasing order and update the table in reverse order of subset size and sum so that each square is used at most once. Whenever a new transition contributes to a state, we clamp the count at 2. After all 100 squares have been processed, the sums with dp[50][s] = 1 are exactly the values in UU, and adding those sums gives the answer.

Pseudocode

Set squares to [1^2, 2^2, ..., 100^2].
Let K = 50.
Compute S_min = 1^2 + 2^2 + ... + 50^2.
Compute S_max = 51^2 + 52^2 + ... + 100^2.

Create a table dp[0..K][0..S_max], initialized to 0.
Interpret dp[j][s] as:
    0 if no j-element subset has sum s,
    1 if exactly one j-element subset has sum s,
    2 if at least two j-element subsets have sum s.
Set dp[0][0] = 1.

For each square a_i in increasing order:
    For subset size j from min(i, K) down to 1:
        Restrict the sum loop to the values that are feasible for j - 1 chosen
        squares among the first i - 1 terms.
        For each such previous sum t, scanned in descending order:
            If dp[j - 1][t] is nonzero:
                Update dp[j][t + a_i] to min(2, dp[j][t + a_i] + dp[j - 1][t]).

answer = 0
For s from S_min to S_max:
    If dp[K][s] = 1:
        answer += s

Return answer

Complexity Analysis

  • Time: In worst-case form the DP is O(n⋅K⋅Smax⁡)O(n \cdot K \cdot S_{\max}), with n=100n = 100, K=50K = 50, and Smax⁡=295425S_{\max} = 295425. The implementation prunes each inner loop to the sum interval that is actually feasible at that stage.
  • Space: O(K⋅Smax⁡)O(K \cdot S_{\max}) for the three-state table.

Answer

115039000\boxed{115039000}

Code

Each problem page includes the exact C++ and Python source files from the local archive.

C++ project_euler/problem_201/solution.cpp
#include <bits/stdc++.h>
using namespace std;

int main() {
    const int N = 100;
    const int K = 50;

    vector<int> squares(N);
    for (int i = 0; i < N; i++) {
        squares[i] = (i + 1) * (i + 1);
    }

    vector<int> prefix(N + 1, 0);
    for (int i = 0; i < N; i++) {
        prefix[i + 1] = prefix[i] + squares[i];
    }

    int minSum = prefix[K];
    int maxSum = prefix[N] - prefix[N - K];

    // dp[j][s] is 0, 1, or 2 depending on whether there are
    // zero, one, or at least two j-element subsets with sum s.
    vector<vector<uint8_t>> dp(K + 1, vector<uint8_t>(maxSum + 1, 0));
    dp[0][0] = 1;

    for (int i = 1; i <= N; i++) {
        int value = squares[i - 1];
        int previousTotal = prefix[i - 1];

        for (int size = min(i, K); size >= 1; size--) {
            int minPrev = prefix[size - 1];
            int maxPrev = previousTotal - prefix[i - size];
            auto& curr = dp[size];
            const auto& prev = dp[size - 1];

            for (int prevSum = maxPrev; prevSum >= minPrev; prevSum--) {
                if (prev[prevSum]) {
                    int newSum = prevSum + value;
                    int total = curr[newSum] + prev[prevSum];
                    curr[newSum] = static_cast<uint8_t>(min(total, 2));
                }
            }
        }
    }

    long long answer = 0;
    for (int sum = minSum; sum <= maxSum; sum++) {
        if (dp[K][sum] == 1) {
            answer += sum;
        }
    }

    cout << answer << '\n';
    return 0;
}