All Euler problems
Project Euler

Product Partition Function

A multiplicative partition (or factorization) of n is a way to write n as an ordered or unordered product of integers greater than 1. Let f(n) denote the number of unordered multiplicative partitio...

Source sync Apr 19, 2026
Problem #0898
Level Level 28
Solved By 347
Languages C++, Python
Answer 0.9861343531
Length 443 words
number_theorydynamic_programmingmodular_arithmetic

Problem Statement

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

Claire Voyant is a teacher playing a game with a class of students. A fair coin is tossed on the table. All the students can see the outcome of the toss, but Claire cannot. Each student then tells Claire whether the outcome is head or tail. The students may lie, but Claire knows the probability that each individual student lies. Moreover, the students lie independently. After that, Claire attempts to guess the outcome using an optimal strategy.

For example, for a class of four students with lying probabilities \(20\%,40\%,60\%,80\%\), Claire guesses correctly with probability 0.832.

Find the probability that Claire guesses correctly for a class of 51 students each lying with a probability of \(25\%, 26\%, \dots , 75\%\) respectively.

Give your answer rounded to 10 digits after the decimal point.

Problem 898: Product Partition Function

Mathematical Analysis

Definition

f(n)=number of unordered factorizations of n into factors>1f(n) = \text{number of unordered factorizations of } n \text{ into factors} > 1

with f(1)=1f(1) = 1 (the empty product).

Theorem 1 (Recursive Formula)

f(n)=1+dn1<d<nf(n/d)[dn/d]f(n) = 1 + \sum_{\substack{d \mid n \\ 1 < d < n}} f(n/d) \cdot [d \leq n/d]

The constraint dn/dd \leq n/d (i.e., dnd \leq \sqrt{n}) avoids double-counting unordered factorizations.

Alternatively, with a minimum-factor parameter:

g(n,m)=dnmdng(n/d,d)+[nm]g(n, m) = \sum_{\substack{d \mid n \\ m \leq d \leq \sqrt{n}}} g(n/d, d) + [n \geq m]

where g(n,m)g(n, m) counts factorizations of nn where all factors are m\geq m, and f(n)=g(n,2)f(n) = g(n, 2).

Theorem 2 (Dirichlet Series)

The generating Dirichlet series satisfies:

n=1f(n)ns=k=211ks\sum_{n=1}^{\infty} \frac{f(n)}{n^s} = \prod_{k=2}^{\infty} \frac{1}{1 - k^{-s}}

This infinite product converges for (s)>1\Re(s) > 1.

Theorem 3 (Dependence on Prime Signature)

f(n)f(n) depends only on the prime signature of nn (the multiset of exponents in the prime factorization). Thus f(12)=f(p2q)f(12) = f(p^2 q) for any distinct primes p,qp, q.

Proof. Any factorization of n=p1a1pkakn = p_1^{a_1} \cdots p_k^{a_k} corresponds to a way of distributing the prime exponents among factors. The specific primes are irrelevant. \square

Lemma (Prime Powers)

For n=pan = p^a, f(pa)f(p^a) equals the number of additive partitions of aa into parts 1\geq 1 (i.e., the ordinary partition function p(a)p(a)… but excluding parts of size 0):

Actually, f(pa)f(p^a) counts the number of ways to write aa as an ordered sum with parts 1\geq 1, disregarding order = the number of additive partitions of aa, which is p(a)p(a).

Wait — not quite. f(pa)f(p^a) counts factorizations of pap^a into factors >1> 1. Each factor peip^{e_i} has ei1e_i \geq 1. So f(pa)=f(p^a) = number of unordered partitions of aa into positive parts =p(a)= p(a) (the standard partition function).

Concrete Numerical Examples

nnFactorizationsf(n)f(n)
2221
444; 2×22 \times 22
666; 2×32 \times 32
888; 2×42 \times 4; 2×2×22 \times 2 \times 23
121212; 2×62 \times 6; 3×43 \times 4; 2×2×32 \times 2 \times 34
161616; 2×82 \times 8; 4×44 \times 4; 2×2×42 \times 2 \times 4; 2×2×2×22 \times 2 \times 2 \times 25
242424; 2×122 \times 12; 3×83 \times 8; 4×64 \times 6; 2×2×62 \times 2 \times 6; 2×3×42 \times 3 \times 4; 2×2×2×32 \times 2 \times 2 \times 37
369 factorizations9

Verification: Prime Powers vs Partition Function

aaf(pa)f(p^a)p(a)p(a)Match
111Yes
222Yes
333Yes
455Yes
577Yes

Cumulative Sum

NNn=2Nf(n)\sum_{n=2}^{N} f(n)
1013
2033
50105
100246

Solution Approaches

Method 1: Recursive with Memoization

Compute g(n,m)g(n, m) recursively, iterating over divisors dmd \geq m with d2nd^2 \leq n. Time: O(Nd(N)N)O(N \cdot d(N) \cdot \sqrt{N}) where d(N)d(N) is the max divisor count.

Method 2: Sieve-like Precomputation

For each dd from 2 to NN, add contributions to multiples of dd. This is akin to the Dirichlet convolution approach.

Method 3: Via Prime Signatures

Group numbers by their prime signature. Compute ff once per signature, then multiply by the count of numbers with that signature.

Complexity Analysis

MethodTimeSpace
Recursive per queryO(d(n)n)O(d(n) \sqrt{n})O(n)O(\sqrt{n})
Sieve up to NNO(NlogN)O(N \log N)O(N)O(N)

Answer

0.9861343531\boxed{0.9861343531}

Code

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

C++ project_euler/problem_898/solution.cpp
/*
 * Problem 898: Product Partition Function
 * Count unordered multiplicative partitions (factorizations) of n.
 * f(n) = number of ways to write n as unordered product of factors > 1.
 *
 * Uses recursive approach with minimum-factor constraint to avoid double counting.
 * f(p^a) = p(a) (additive partition function).
 */
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

unordered_map<ll, ll> memo;

// Encode (n, min_factor) into single key for memoization
ll encode(ll n, ll m) { return n * 100001LL + m; }

ll factorizations(ll n, ll min_factor = 2) {
    if (n < min_factor) return 0;
    ll key = encode(n, min_factor);
    auto it = memo.find(key);
    if (it != memo.end()) return it->second;

    ll count = 1;  // n itself as single factor
    for (ll d = min_factor; d * d <= n; d++) {
        if (n % d == 0) {
            count += factorizations(n / d, d);
        }
    }
    return memo[key] = count;
}

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

    // Verification
    cout << "=== Multiplicative Partitions ===" << endl;
    vector<pair<int,int>> tests = {
        {2,1},{4,2},{6,2},{8,3},{12,4},{16,5},{24,7},{36,9},{48,12},{64,15}
    };
    for (auto [n, expected] : tests) {
        ll fn = factorizations(n);
        cout << "f(" << n << ") = " << fn
             << (fn == expected ? " OK" : " FAIL") << endl;
        assert(fn == expected);
    }

    // Prime powers: f(2^a) should equal partition function p(a)
    cout << "\n=== Prime Powers ===" << endl;
    int part[] = {0, 1, 2, 3, 5, 7, 11, 15, 22, 30, 42};
    for (int a = 1; a <= 10; a++) {
        ll fn = factorizations(1LL << a);
        cout << "f(2^" << a << ") = " << fn
             << ", p(" << a << ") = " << part[a]
             << (fn == part[a] ? " OK" : " FAIL") << endl;
    }

    // Cumulative sum
    cout << "\n=== Cumulative Sum ===" << endl;
    for (int N : {10, 50, 100, 500, 1000}) {
        ll s = 0;
        for (int n = 2; n <= N; n++) s += factorizations(n);
        cout << "sum_{n=2}^{" << N << "} f(n) = " << s << endl;
    }

    ll ans = 0;
    for (int n = 2; n <= 1000; n++) ans += factorizations(n);
    cout << "\nAnswer: " << ans << endl;

    return 0;
}