All Euler problems
Project Euler

Counting Summations

It is possible to write five as a sum in exactly six different ways: How many different ways can one hundred be written as a sum of at least two positive integers?

Source sync Apr 19, 2026
Problem #0076
Level Level 02
Solved By 32,171
Languages C++, Python
Answer 190569291
Length 696 words
dynamic_programmingsequenceanalytic_math

Problem Statement

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

It is possible to write five as a sum in exactly six different ways: \begin {align*} &4 + 1\\ &3 + 2\\ &3 + 1 + 1\\ &2 + 2 + 1\\ &2 + 1 + 1 + 1\\ &1 + 1 + 1 + 1 + 1 \end {align*}

How many different ways can one hundred be written as a sum of at least two positive integers?

Problem 76: Counting Summations

Mathematical Foundation

Definition 1 (Integer Partition). A partition of a non-negative integer nn is a multiset {a1,a2,,ak}\{a_1, a_2, \ldots, a_k\} of positive integers satisfying i=1kai=n\sum_{i=1}^{k} a_i = n. Two partitions are identical if and only if they contain the same parts with the same multiplicities. The partition function p(n)p(n) counts the number of partitions of nn. By convention, p(0)=1p(0) = 1 (the empty partition).

Definition 2 (Restricted Partition). Let pm(n)p_{\le m}(n) denote the number of partitions of nn into parts each at most mm. Equivalently, pm(n)p_{\le m}(n) counts the number of solutions in non-negative integers (c1,c2,,cm)(c_1, c_2, \ldots, c_m) to k=1mkck=n\sum_{k=1}^{m} k \cdot c_k = n, where ckc_k represents the multiplicity of part kk. Note that p(n)=pn(n)p(n) = p_{\le n}(n).

Theorem 1 (Generating Function for p(n)p(n)). The ordinary generating function for the partition function is

n=0p(n)xn=k=111xk.\sum_{n=0}^{\infty} p(n)\,x^n = \prod_{k=1}^{\infty} \frac{1}{1 - x^k}.

Proof. For each positive integer kk, the geometric series 11xk=ck=0xckk\frac{1}{1-x^k} = \sum_{c_k=0}^{\infty} x^{c_k \cdot k} encodes the choice of ck0c_k \geq 0 copies of part kk contributing ckkc_k \cdot k to the total. The Cauchy product of all such series over k1k \geq 1 yields

k=111xk=n=0(c1,c2,0kkck=n1)xn=n=0p(n)xn.\prod_{k=1}^{\infty} \frac{1}{1-x^k} = \sum_{n=0}^{\infty} \left(\sum_{\substack{c_1, c_2, \ldots \geq 0 \\ \sum_k k c_k = n}} 1\right) x^n = \sum_{n=0}^{\infty} p(n)\,x^n.

Absolute convergence for x<1|x| < 1 follows from k=1log11xkk=1xk1xk<\sum_{k=1}^{\infty} \log\frac{1}{1-|x|^k} \leq \sum_{k=1}^{\infty} \frac{|x|^k}{1-|x|^k} < \infty, since the terms are O(xk)O(|x|^k) and xk\sum |x|^k converges. \blacksquare

Theorem 2 (Euler’s Pentagonal Number Theorem). As formal power series (and for x<1|x| < 1):

k=1(1xk)=j=(1)jxj(3j1)/2=1+j=1(1)j(xj(3j1)/2+xj(3j+1)/2).\prod_{k=1}^{\infty}(1 - x^k) = \sum_{j=-\infty}^{\infty} (-1)^j x^{j(3j-1)/2} = 1 + \sum_{j=1}^{\infty} (-1)^j \bigl(x^{j(3j-1)/2} + x^{j(3j+1)/2}\bigr).

Proof (Franklin’s Involution). The coefficient of xnx^n on the left is λDn(1)(λ)\sum_{\lambda \in \mathcal{D}_n} (-1)^{\ell(\lambda)}, where Dn\mathcal{D}_n denotes the set of partitions of nn into distinct parts and (λ)\ell(\lambda) is the number of parts.

For λ=(λ1>λ2>>λr)Dn\lambda = (\lambda_1 > \lambda_2 > \cdots > \lambda_r) \in \mathcal{D}_n, define two parameters:

  • s(λ)=λrs(\lambda) = \lambda_r: the smallest part.
  • t(λ)t(\lambda): the length of the maximal sequence of consecutive integers descending from λ1\lambda_1. That is, t(λ)=max{m1:λ1i+1{λ1,,λr} for all 1im}t(\lambda) = \max\{m \geq 1 : \lambda_1 - i + 1 \in \{\lambda_1, \ldots, \lambda_r\} \text{ for all } 1 \leq i \leq m\}.

Define the map ϕ:DnDn\phi: \mathcal{D}_n \to \mathcal{D}_n as follows:

  • Move A (applicable when s<ts < t, or when s=ts = t and λrλ1t+1\lambda_r \neq \lambda_1 - t + 1): Remove the smallest part λr=s\lambda_r = s and add 11 to each of the ss largest parts λ1,λ2,,λs\lambda_1, \lambda_2, \ldots, \lambda_s. This produces a partition with r1r - 1 distinct parts.
  • Move B (applicable when s>ts > t, or when Move A is inapplicable): Subtract 11 from each of the tt largest parts λ1,,λt\lambda_1, \ldots, \lambda_t, and insert tt as a new smallest part. This produces a partition with r+1r + 1 distinct parts.

One verifies that (i) Moves A and B are mutual inverses, (ii) each changes (λ)\ell(\lambda) by exactly ±1\pm 1, hence reverses the sign (1)(λ)(-1)^{\ell(\lambda)}, and (iii) the map ϕ\phi is undefined (yielding fixed points) precisely when the two moves coincide or become degenerate. This occurs when:

  • s=ts = t and λr=λ1t+1\lambda_r = \lambda_1 - t + 1: partition is (r,r+1,,2r1)(r, r+1, \ldots, 2r-1), giving n=r(3r1)/2n = r(3r-1)/2.
  • s=t+1s = t + 1 and r=sr = s: gives n=r(3r+1)/2n = r(3r+1)/2.

At these fixed points the sign contribution is (1)r(-1)^r. For all other λ\lambda, the map ϕ\phi pairs each partition with one of opposite sign, so the net contribution cancels. \blacksquare

Theorem 3 (Partition Recurrence via Pentagonal Numbers). For n1n \geq 1:

p(n)=j=1(1)j+1[p ⁣(nj(3j1)2)+p ⁣(nj(3j+1)2)],p(n) = \sum_{j=1}^{\infty} (-1)^{j+1} \left[p\!\left(n - \tfrac{j(3j-1)}{2}\right) + p\!\left(n - \tfrac{j(3j+1)}{2}\right)\right],

where p(0)=1p(0) = 1, p(m)=0p(m) = 0 for m<0m < 0, and the sum terminates when both pentagonal arguments become negative.

Proof. Multiplying the generating functions from Theorems 1 and 2:

(n=0p(n)xn)(k=1(1xk))=1.\left(\sum_{n=0}^{\infty} p(n)x^n\right)\left(\prod_{k=1}^{\infty}(1-x^k)\right) = 1.

Extracting the coefficient of xnx^n for n1n \geq 1:

p(n)+j=1(1)j[p ⁣(nj(3j1)2)+p ⁣(nj(3j+1)2)]=0.p(n) + \sum_{j=1}^{\infty} (-1)^j \left[p\!\left(n - \tfrac{j(3j-1)}{2}\right) + p\!\left(n - \tfrac{j(3j+1)}{2}\right)\right] = 0.

Rearranging and noting that (1)j(1)=(1)j+1(-1)^{j} \cdot (-1) = (-1)^{j+1} yields the stated recurrence. \blacksquare

Theorem 4 (Correctness of Partition DP). Define the array dp[0..n]\mathrm{dp}[0..n] by dp[0]=1\mathrm{dp}[0] = 1, dp[j]=0\mathrm{dp}[j] = 0 for 1jn1 \leq j \leq n. For k=1,2,,nk = 1, 2, \ldots, n and for j=k,k+1,,nj = k, k+1, \ldots, n, perform dp[j]+=dp[jk]\mathrm{dp}[j] \mathrel{+}= \mathrm{dp}[j - k]. Then upon termination, dp[n]=p(n)\mathrm{dp}[n] = p(n).

Proof. We prove by induction on kk that after processing part size kk, the value dp[j]\mathrm{dp}[j] equals pk(j)p_{\le k}(j) for all 0jn0 \leq j \leq n.

Base case (k=0k = 0): Before any updates, dp[0]=1=p0(0)\mathrm{dp}[0] = 1 = p_{\le 0}(0) and dp[j]=0=p0(j)\mathrm{dp}[j] = 0 = p_{\le 0}(j) for j1j \geq 1. This is correct since the only partition using parts 0\leq 0 is the empty partition of 00.

Inductive step: Assume dp[j]=pk1(j)\mathrm{dp}[j] = p_{\le k-1}(j) for all jj before processing part size kk. The update loop sets dp[j]dp[j]+dp[jk]\mathrm{dp}[j] \leftarrow \mathrm{dp}[j] + \mathrm{dp}[j - k] for j=k,k+1,,nj = k, k+1, \ldots, n. After this pass, dp[j]\mathrm{dp}[j] accumulates:

dp[j]=pk1(j)+m=1j/kpk1(jmk),\mathrm{dp}[j] = p_{\le k-1}(j) + \sum_{m=1}^{\lfloor j/k \rfloor} p_{\le k-1}(j - mk),

since the forward iteration (increasing jj) allows the value dp[jk]\mathrm{dp}[j - k] to already reflect uses of part kk. This telescopes to the partition identity pk(j)=m=0j/kpk1(jmk)p_{\le k}(j) = \sum_{m=0}^{\lfloor j/k \rfloor} p_{\le k-1}(j - mk), which counts partitions of jj with parts k\leq k by conditioning on the multiplicity mm of part kk. After k=nk = n, we have dp[n]=pn(n)=p(n)\mathrm{dp}[n] = p_{\le n}(n) = p(n). \blacksquare

Remark. The problem asks for partitions into at least two parts, which excludes the trivial partition n=nn = n. The answer is therefore p(100)1p(100) - 1.

Editorial

This is the standard partition DP in unbounded-knapsack form. We process possible part sizes in increasing order, and after part size kk is handled, the table entry for a sum jj represents the number of partitions of jj that use only parts up to kk.

The update is natural: every partition of jkj-k can be extended by adding one more part of size kk, so we add the number of ways to make jkj-k into the number of ways to make jj. Because part sizes are introduced in sorted order, the same multiset is never counted in different orders. That is exactly why the DP counts partitions rather than compositions. At the end we subtract one to remove the trivial partition consisting of 100100 alone.

Pseudocode

Create a table for sums from 0 to 100 and fill it with zeros.
Set the entry for sum 0 to 1.

For each allowed part size from 1 to 100:
    For each target sum that can include this part:
        add the number of ways to form the remaining sum after taking one such part

Subtract one to exclude the single-part partition 100.
Return the resulting count.

Complexity Analysis

Time: The nested loops execute k=1n(nk+1)=i=1ni=n(n+1)/2=O(n2)\sum_{k=1}^{n}(n - k + 1) = \sum_{i=1}^{n} i = n(n+1)/2 = O(n^2) iterations, each performing O(1)O(1) arithmetic. For n=100n = 100, this is 50505050 operations.

Space: The one-dimensional DP array requires n+1=O(n)n + 1 = O(n) entries.

Alternative: The pentagonal number recurrence (Theorem 3) computes each p(k)p(k) in O(k)O(\sqrt{k}) time, yielding O(nn)O(n\sqrt{n}) total time.

Answer

190569291\boxed{190569291}

Code

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

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

int main() {
    const int N = 100;
    vector<long long> dp(N + 1, 0);
    dp[0] = 1;

    // Partition DP: for each part size k, update dp[j] += dp[j - k]
    for (int k = 1; k <= N; k++)
        for (int j = k; j <= N; j++)
            dp[j] += dp[j - k];

    // p(100) - 1: exclude the trivial partition 100 = 100
    cout << dp[N] - 1 << endl;
    return 0;
}