All Euler problems
Project Euler

Special Partitions

A number of the form 2^a * 3^b with a, b >= 0 is called a 3-smooth power. A positive integer n has a special partition if it can be written as a sum of distinct 3-smooth powers. A prime p is called...

Source sync Apr 19, 2026
Problem #0333
Level Level 13
Solved By 1,446
Languages C++, Python
Answer 3053105
Length 349 words
dynamic_programmingnumber_theorylinear_algebra

Problem Statement

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

All positive integers can be partitioned in such a way that each and every term of the partition can be expressed as \(2^i \times 3^j\), where \(i,j \ge 0\).

Let’s consider only such partitions where none of the terms can divide any of the other terms.

For example, the partition of \(17 = 2 + 6 + 9 = (2^1 \times 3^0 + 2^1 \times 3^1 + 2^0 \times 3^2)\) would not be valid since \(2\) can divide \(6\). Neither would the partition \(17 = 16 + 1 = (2^4 \times 3^0 + 2^0 \times 3^0)\) since \(1\) can divide \(16\). The only valid partition of \(17\) would be \(8 + 9 = (2^3 \times 3^0 + 2^0 \times 3^2)\).

Many integers have more than one valid partition, the first being \(11\) having the following two partitions.

\(11 = 2 + 9 = (2^1 \times 3^0 + 2^0 \times 3^2)\)

\(11 = 8 + 3 = (2^3 \times 3^0 + 2^0 \times 3^1)\)

Let’s define \(P(n)\) as the number of valid partitions of \(n\). For example, \(P(11) = 2\).

Let’s consider only the prime integers \(q\) which would have a single valid partition such as \(P(17)\).

The sum of the primes \(q < 100\) such that \(P(q)=1\) equals \(233\).

Find the sum of the primes \(q < 1000000\) such that \(P(q)=1\).

Problem 333: Special Partitions

Mathematical Foundation

Definition. Let T={2a3b:a0,  b0}={1,2,3,4,6,8,9,12,16,18,}T = \{2^a \cdot 3^b : a \ge 0,\; b \ge 0\} = \{1, 2, 3, 4, 6, 8, 9, 12, 16, 18, \ldots\} be the set of all 3-smooth powers.

Lemma 1 (Finiteness of TT below NN). The number of elements of TT not exceeding NN is T[1,N]=O(log2N)|T \cap [1, N]| = O(\log^2 N).

Proof. Each element 2a3bN2^a \cdot 3^b \le N requires alog2Na \le \log_2 N and blog3Nb \le \log_3 N. The number of valid pairs (a,b)(a,b) is at most (log2N+1)(log3N+1)=O(log2N)(\lfloor \log_2 N \rfloor + 1)(\lfloor \log_3 N \rfloor + 1) = O(\log^2 N). \square

For N=106N = 10^6: log2(106)19.93\log_2(10^6) \approx 19.93 and log3(106)12.58\log_3(10^6) \approx 12.58, giving at most 20×13=26020 \times 13 = 260 terms.

Theorem 1 (0-1 Knapsack Reduction). The number of ways to write nn as a sum of distinct elements of T[1,N]T \cap [1, N] equals the coefficient of xnx^n in the product

tT[1,N](1+xt).\prod_{t \in T \cap [1,N]} (1 + x^t).

Proof. Expanding the product, each monomial xti1+ti2++tikx^{t_{i_1} + t_{i_2} + \cdots + t_{i_k}} corresponds to choosing a distinct subset {ti1,,tik}T\{t_{i_1}, \ldots, t_{i_k}\} \subseteq T. The coefficient of xnx^n counts the number of such subsets summing to nn. \square

Lemma 2 (DP Correctness). Processing items in any order and updating in reverse (standard 0-1 knapsack), the array dp[s]\mathrm{dp}[s] correctly counts the number of representations of ss as a sum of distinct elements of TT.

Proof. By induction on the number of items processed. After processing item tkt_k, for each sum ss, dp[s]\mathrm{dp}[s] equals the number of subsets of {t1,,tk}\{t_1, \ldots, t_k\} summing to ss. The reverse-order update ensures each item is used at most once, since when computing dp[s+tk]\mathrm{dp}[s + t_k], the value dp[s]\mathrm{dp}[s] has not yet been modified in the current pass. \square

Theorem 2 (Characterization of Special Primes). A prime p<106p < 10^6 is special if and only if dp[p]=1\mathrm{dp}[p] = 1 after the full knapsack computation. The answer is p specialp\sum_{p \text{ special}} p.

Proof. By definition, pp is special if and only if it admits exactly one partition into distinct 3-smooth powers, which is precisely dp[p]=1\mathrm{dp}[p] = 1. \square

Editorial

Approach: 1. Generate all numbers 2^a * 3^b < 10^6. 2. 0-1 knapsack DP to count representations (capped at 2). 3. Sieve primes, sum those with exactly 1 representation. We generate 3-smooth powers up to N. We then 0-1 knapsack DP (count representations, cap at 2). Finally, iterate over t in T.

Pseudocode

Generate 3-smooth powers up to N
0-1 knapsack DP (count representations, cap at 2)
for t in T
for s from N-1 down to t
Sieve primes up to N
Sum special primes
for p from 2 to N-1

Complexity Analysis

  • Time: Generating TT takes O(log2N)O(\log^2 N). The knapsack DP runs in O(TN)=O(Nlog2N)O(|T| \cdot N) = O(N \log^2 N). The prime sieve takes O(NloglogN)O(N \log \log N). Total: O(Nlog2N)O(N \log^2 N).
  • Space: O(N)O(N) for the DP array and the prime sieve.

Answer

3053105\boxed{3053105}

Code

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

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

/*
 * Problem 333: Special Partitions
 *
 * Find the sum of all primes < 10^6 that can be written in exactly one way
 * as a sum of distinct terms of the form 2^a * 3^b.
 *
 * Approach:
 * 1. Generate all numbers 2^a * 3^b < 10^6.
 * 2. 0-1 knapsack DP to count representations (capped at 2).
 * 3. Sieve primes, sum those with exactly 1 representation.
 *
 * Answer: 3053105
 */

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    const int LIMIT = 1000000;

    // Generate all 2^a * 3^b < LIMIT
    vector<int> terms;
    for (long long b3 = 1; b3 < LIMIT; b3 *= 3) {
        for (long long val = b3; val < LIMIT; val *= 2) {
            terms.push_back((int)val);
        }
    }
    sort(terms.begin(), terms.end());

    cout << "Number of terms: " << terms.size() << endl;

    // 0-1 knapsack: count representations, cap at 2
    // dp[s] = number of ways to represent s (capped at 2)
    vector<unsigned char> dp(LIMIT, 0);
    dp[0] = 1;

    for (int t : terms) {
        // Process in reverse for 0-1 knapsack
        for (int s = LIMIT - 1 - t; s >= 0; s--) {
            if (dp[s] > 0 && dp[s + t] < 2) {
                dp[s + t] = min(2, (int)dp[s + t] + (int)dp[s]);
            }
        }
    }

    // Sieve of Eratosthenes
    vector<bool> is_prime(LIMIT, true);
    is_prime[0] = is_prime[1] = false;
    for (int i = 2; i * i < LIMIT; i++) {
        if (is_prime[i]) {
            for (int j = i * i; j < LIMIT; j += i)
                is_prime[j] = false;
        }
    }

    // Sum primes with exactly 1 representation
    long long answer = 0;
    int count = 0;
    for (int p = 2; p < LIMIT; p++) {
        if (is_prime[p] && dp[p] == 1) {
            answer += p;
            count++;
        }
    }

    cout << "Number of special primes: " << count << endl;
    cout << "Answer: " << answer << endl;

    return 0;
}