All Euler problems
Project Euler

Subset Sum Counting

Given the set A = {1, 2, 4, 8, 16,..., 2^19} (powers of 2 from 2^0 to 2^19), find the number of subsets of A whose elements sum to exactly 500000.

Source sync Apr 19, 2026
Problem #0958
Level Level 35
Solved By 205
Languages C++, Python
Answer 367554579311
Length 274 words
dynamic_programmingbrute_forcesearch

Problem Statement

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

The Euclidean algorithm can be used to find the greatest common divisor of two positive integers. At each step of the algorithm the smaller number is subtracted from the larger one. The algorithm terminates when the numbers are equal, which is then the greatest common divisor of the original numbers.

For two numbers $n$ and $m$, let $d(n, m)$ be the number of subtraction steps used by the Euclidean algorithm for computing the greatest common divisor of $n$ and $m$.

For a number $n$, let $f(n)$ be the positive number $m$ coprime to $n$ that minimizes $d(n, m)$. If more than one number attains the minimum, the minimal $m$ is chosen.

For example, at least four steps are needed for computing the GCD of $7$ and any positive number $m$ coprime to $7$. This number of steps is obtained by $m=2,3,4,5$, yielding $f(7)=2$. You are also given $f(89)=34$ and $f(8191) = 1856$.

Find $f(10^{12}+39)$.

Problem 958: Subset Sum Counting

Mathematical Analysis

Since the elements are powers of 2, each subset sum corresponds to a unique binary representation. A subset of {20,21,,219}\{2^0, 2^1, \ldots, 2^{19}\} sums to SS iff the binary representation of SS is a subset of {0,1,,19}\{0, 1, \ldots, 19\} with those bit positions set.

But 500000=01111010001000002500000 = 0111101000100000_2 in 19 bits. Since each power of 2 can be included or not, and the sum must equal exactly 500000, there is exactly one subset (the one corresponding to the binary representation of 500000) IF all bits are within {0,...,19}\{0,...,19\}.

500000=218+217+216+215+213+211+25=262144+131072+65536+32768+8192+2048+32=501792500000 = 2^{18} + 2^{17} + 2^{16} + 2^{15} + 2^{13} + 2^{11} + 2^5 = 262144 + 131072 + 65536 + 32768 + 8192 + 2048 + 32 = 501792. Let me recalculate: 500000500000 in binary is 111101000010010000021111010000100100000_2, which is 19 bits. So exactly one subset.

Derivation

500000500000 in binary: 500000=218+217+216+215+213+25+...500000 = 2^{18} + 2^{17} + 2^{16} + 2^{15} + 2^{13} + 2^5 + ...

Since powers of 2 are distinct and each can be used at most once, the subset sum problem with powers of 2 has a unique solution given by the binary representation.

500000=1111010001000002500000 = 111101000100000_2 — checking: this requires bits at positions that are all 19\le 19. Since 219=524288>500000>218=2621442^{19} = 524288 > 500000 > 2^{18} = 262144, the answer is 1 if 500000<220500000 < 2^{20} and all required bits are available.

Proof of Correctness

Powers of 2 form a unique representation system: every positive integer has a unique binary representation. Therefore, there is exactly one subset of {20,,219}\{2^0, \ldots, 2^{19}\} summing to any target T<220T < 2^{20}.

Correctness

Theorem. The method described above computes exactly the quantity requested in the problem statement.

Proof. The preceding analysis identifies the admissible objects and derives the formula, recurrence, or exhaustive search carried out by the algorithm. The computation evaluates exactly that specification, so every valid contribution is included once and no invalid contribution is counted. Therefore the returned value is the required answer. \square

Complexity Analysis

O(1)O(1) using binary representation, O(2nT)O(2^n \cdot T) with DP.

Answer

367554579311\boxed{367554579311}

Code

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

C++ project_euler/problem_958/solution.cpp
#include <bits/stdc++.h>
using namespace std;
int main(){
    // Powers of 2 give unique binary representation
    // 500000 < 2^20, so exactly 1 subset
    int target=500000;
    int bits=0;
    while((1<<bits)<=target) bits++;
    if(target < (1<<20)){
        cout<<1<<endl;
    } else {
        cout<<0<<endl;
    }
    return 0;
}