All Euler problems
Project Euler

Investigating in How Many Ways Objects of Two Different Colours Can Be Grouped

How many ways can 60 black objects and 40 white objects be grouped into non-empty groups, where the order of groups does not matter and each group is characterized by the pair (b, w) denoting the n...

Source sync Apr 19, 2026
Problem #0181
Level Level 10
Solved By 2,393
Languages C++, Python
Answer 83735848679360680
Length 411 words
dynamic_programminganalytic_mathlinear_algebra

Problem Statement

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

Having three black objects B and one white object W they can be grouped in 7 ways like this: \[(BBBW) \quad (B,BBW) \quad (B,B,BW) \quad (B,B,B,W) \quad (B,BB,W) \quad (BBB,W) \quad (BB,BW)\] In how many ways can sixty black objects B and forty white objects W be thus grouped?

Problem 181: Investigating in How Many Ways Objects of Two Different Colours Can Be Grouped

Mathematical Development

Definition 1. A bicolour partition of the pair (B,W)Z02(B, W) \in \mathbb{Z}_{\geq 0}^2 is a multiset {(b1,w1),(b2,w2),,(bk,wk)}\{(b_1, w_1), (b_2, w_2), \ldots, (b_k, w_k)\} of elements from Z02{(0,0)}\mathbb{Z}_{\geq 0}^2 \setminus \{(0,0)\} satisfying

i=1kbi=Bandi=1kwi=W.\sum_{i=1}^{k} b_i = B \quad \text{and} \quad \sum_{i=1}^{k} w_i = W.

Let P(B,W)P(B, W) denote the number of such bicolour partitions. We seek P(60,40)P(60, 40).

Theorem 1 (Generating Function). The bicolour partition function satisfies

B=0W=0P(B,W)xByW=(b,w)Z02(b,w)(0,0)11xbyw.\sum_{B=0}^{\infty} \sum_{W=0}^{\infty} P(B, W)\, x^B y^W = \prod_{\substack{(b, w) \in \mathbb{Z}_{\geq 0}^2 \\ (b,w) \neq (0,0)}} \frac{1}{1 - x^b y^w}.

Proof. The set of admissible part types is P=Z02{(0,0)}\mathcal{P} = \mathbb{Z}_{\geq 0}^2 \setminus \{(0,0)\}. A bicolour partition is a function μ:PZ0\mu: \mathcal{P} \to \mathbb{Z}_{\geq 0} assigning a multiplicity to each part type, subject to (b,w)μ(b,w)b=B\sum_{(b,w)} \mu(b,w) \cdot b = B and (b,w)μ(b,w)w=W\sum_{(b,w)} \mu(b,w) \cdot w = W. The generating function for the multiplicity of a single part type (b,w)(b,w) is the geometric series

k=0(xbyw)k=11xbyw.\sum_{k=0}^{\infty} (x^b y^w)^k = \frac{1}{1 - x^b y^w}.

Since the part types are independent, the total generating function is the product over all part types. The coefficient [xByW][x^B y^W] of this product counts the number of multisets with the prescribed totals, which is precisely P(B,W)P(B, W). \square

Theorem 2 (Unbounded Knapsack Reduction). Let the part types be enumerated in an arbitrary fixed total order as p1,p2,,pMp_1, p_2, \ldots, p_M where M=(B+1)(W+1)1M = (B+1)(W+1) - 1. Define fj(b,w)f_j(b, w) as the number of bicolour partitions of (b,w)(b, w) using only part types from {p1,,pj}\{p_1, \ldots, p_j\}. Then f0(0,0)=1f_0(0,0) = 1, f0(b,w)=0f_0(b, w) = 0 for (b,w)(0,0)(b,w) \neq (0,0), and for each j1j \geq 1 with pj=(δb,δw)p_j = (\delta_b, \delta_w):

fj(b,w)=t=0min(b/δb,w/δw)fj1(btδb,wtδw).f_j(b, w) = \sum_{t=0}^{\lfloor \min(b/\delta_b,\, w/\delta_w) \rfloor} f_{j-1}(b - t\delta_b,\, w - t\delta_w).

Proof. By the principle of sequential decision: for each part type pjp_j, choose its multiplicity t0t \geq 0, then count partitions of the residual (btδb,wtδw)(b - t\delta_b, w - t\delta_w) using only the preceding part types. The base case f0f_0 reflects the empty partition of (0,0)(0,0). \square

Corollary 1 (In-Place Computation). If part types are processed sequentially and, for each part type (δb,δw)(\delta_b, \delta_w), the table is updated via

dp[b][w]+=dp[bδb][wδw]\mathrm{dp}[b][w] \mathrel{+}= \mathrm{dp}[b - \delta_b][w - \delta_w]

with bb ranging from δb\delta_b to BB and ww from δw\delta_w to WW in increasing order, then after processing all part types, dp[B][W]=P(B,W)\mathrm{dp}[B][W] = P(B, W).

Proof. This is the standard unbounded knapsack transformation. Iterating in increasing order permits each part type to be used with unlimited multiplicity. The in-place update telescopes the summation in Theorem 2, since after processing part pjp_j, the entry dp[b][w]\mathrm{dp}[b][w] equals fj(b,w)f_j(b, w). The proof proceeds by induction on jj: the base case j=0j = 0 holds by initialization; for the inductive step, the forward-sweep update accumulates exactly the sum t0fj1(btδb,wtδw)\sum_{t \geq 0} f_{j-1}(b - t\delta_b, w - t\delta_w). \square

Editorial

Different Colours Can Be Grouped Count the number of bicolour partitions of (60, 40), i.e., the number of unordered groupings of 60 black and 40 white objects into non-empty groups. Uses two-dimensional unbounded knapsack DP.

Pseudocode

    Set dp[0..B][0..W] <- 0
    Set dp[0][0] <- 1

    For db from 0 to B:
        For dw from 0 to W:
            If db = 0 and dw = 0 then continue
            For b from db to B:
                For w from dw to W:
                    dp[b][w] += dp[b - db][w - dw]

    Return dp[B][W]

Complexity Analysis

  • Time: The outer double loop iterates over M=(B+1)(W+1)1M = (B+1)(W+1) - 1 part types. For each part type (δb,δw)(\delta_b, \delta_w), the inner loop performs (Bδb+1)(Wδw+1)BW(B - \delta_b + 1)(W - \delta_w + 1) \leq B \cdot W updates. Hence the total work is O(B2W2)O(B^2 W^2). For (B,W)=(60,40)(B, W) = (60, 40), this yields approximately 602402=5,760,00060^2 \cdot 40^2 = 5{,}760{,}000 operations.
  • Space: O(BW)O(B \cdot W) for the two-dimensional DP table.

Answer

83735848679360680\boxed{83735848679360680}

Code

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

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

int main() {
    const int B = 60, W = 40;
    vector<vector<long long>> dp(B + 1, vector<long long>(W + 1, 0));
    dp[0][0] = 1;

    for (int db = 0; db <= B; db++) {
        for (int dw = 0; dw <= W; dw++) {
            if (db == 0 && dw == 0) continue;
            for (int b = db; b <= B; b++) {
                for (int w = dw; w <= W; w++) {
                    dp[b][w] += dp[b - db][w - dw];
                }
            }
        }
    }

    cout << dp[B][W] << endl;
    return 0;
}