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...
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
with (the empty product).
Theorem 1 (Recursive Formula)
The constraint (i.e., ) avoids double-counting unordered factorizations.
Alternatively, with a minimum-factor parameter:
where counts factorizations of where all factors are , and .
Theorem 2 (Dirichlet Series)
The generating Dirichlet series satisfies:
This infinite product converges for .
Theorem 3 (Dependence on Prime Signature)
depends only on the prime signature of (the multiset of exponents in the prime factorization). Thus for any distinct primes .
Proof. Any factorization of corresponds to a way of distributing the prime exponents among factors. The specific primes are irrelevant.
Lemma (Prime Powers)
For , equals the number of additive partitions of into parts (i.e., the ordinary partition function … but excluding parts of size 0):
Actually, counts the number of ways to write as an ordered sum with parts , disregarding order = the number of additive partitions of , which is .
Wait — not quite. counts factorizations of into factors . Each factor has . So number of unordered partitions of into positive parts (the standard partition function).
Concrete Numerical Examples
| Factorizations | ||
|---|---|---|
| 2 | 1 | |
| 4 | ; | 2 |
| 6 | ; | 2 |
| 8 | ; ; | 3 |
| 12 | ; ; ; | 4 |
| 16 | ; ; ; ; | 5 |
| 24 | ; ; ; ; ; ; | 7 |
| 36 | 9 factorizations | 9 |
Verification: Prime Powers vs Partition Function
| Match | |||
|---|---|---|---|
| 1 | 1 | 1 | Yes |
| 2 | 2 | 2 | Yes |
| 3 | 3 | 3 | Yes |
| 4 | 5 | 5 | Yes |
| 5 | 7 | 7 | Yes |
Cumulative Sum
| 10 | 13 |
| 20 | 33 |
| 50 | 105 |
| 100 | 246 |
Solution Approaches
Method 1: Recursive with Memoization
Compute recursively, iterating over divisors with . Time: where is the max divisor count.
Method 2: Sieve-like Precomputation
For each from 2 to , add contributions to multiples of . This is akin to the Dirichlet convolution approach.
Method 3: Via Prime Signatures
Group numbers by their prime signature. Compute once per signature, then multiply by the count of numbers with that signature.
Complexity Analysis
| Method | Time | Space |
|---|---|---|
| Recursive per query | ||
| Sieve up to |
Answer
Code
Each problem page includes the exact C++ and Python source files from the local archive.
/*
* 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;
}
"""
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.
"""
from functools import lru_cache
from math import isqrt
def factorizations(n, min_factor=2):
"""Count unordered factorizations of n with all factors >= min_factor."""
count = 1 # n itself (if n >= min_factor)
d = min_factor
while d * d <= n:
if n % d == 0:
count += factorizations(n // d, d)
d += 1
return count
@lru_cache(maxsize=None)
def f_cached(n, m=2):
"""Memoized version."""
if n < m:
return 0
count = 1 # n itself as a single factor
d = m
while d * d <= n:
if n % d == 0:
count += f_cached(n // d, d)
d += 1
return count
def f_sieve(N):
"""Sieve-based computation of f(n) for all n up to N."""
# g[n] = number of factorizations of n with smallest factor >= 2
g = [0] * (N + 1)
g[1] = 1
for n in range(2, N + 1):
g[n] = 1 # n itself
d = 2
while d * d <= n:
if n % d == 0:
# Add factorizations starting with d, recursively
# but this requires the min_factor constraint
pass
d += 1
# Simpler: just use the cached version
return [f_cached(n) for n in range(N + 1)]
def get_divisors(n):
"""Return all divisors of n."""
divs = []
for d in range(1, isqrt(n) + 1):
if n % d == 0:
divs.append(d)
if d != n // d:
divs.append(n // d)
return sorted(divs)
# --- Verification ---
print("=== Multiplicative Partitions f(n) ===")
print(f"{'n':>4} {'f(n)':>6} Factorizations")
test_cases = {
2: 1, 4: 2, 6: 2, 8: 3, 12: 4, 16: 5, 24: 7, 36: 9, 48: 12, 64: 15
}
for n in sorted(test_cases.keys()):
fn = f_cached(n)
expected = test_cases[n]
status = "OK" if fn == expected else f"FAIL(expected {expected})"
print(f"{n:>4} {fn:>6} {status}")
assert fn == expected, f"f({n})={fn} != {expected}"
# List factorizations of 12 explicitly
print("\n=== Factorizations of 12 ===")
def list_factorizations(n, min_f=2, prefix=()):
results = []
results.append(prefix + (n,))
d = min_f
while d * d <= n:
if n % d == 0:
results.extend(list_factorizations(n // d, d, prefix + (d,)))
d += 1
return results
for fz in list_factorizations(12):
print(f" {' x '.join(map(str, fz))}")
# Prime power verification: f(p^a) = p(a), the partition function
print("\n=== Prime Power: f(2^a) vs partition p(a) ===")
partitions = {1: 1, 2: 2, 3: 3, 4: 5, 5: 7, 6: 11, 7: 15}
for a in range(1, 8):
fn = f_cached(2 ** a)
pa = partitions[a]
print(f" f(2^{a}) = {fn}, p({a}) = {pa}, Match: {'OK' if fn == pa else 'FAIL'}")
assert fn == pa
# Cumulative sum
print("\n=== Cumulative Sum ===")
for N in [10, 20, 50, 100, 200, 500]:
s = sum(f_cached(n) for n in range(2, N + 1))
print(f" sum_{{n=2}}^{{{N}}} f(n) = {s}")
answer = sum(f_cached(n) for n in range(2, 1001))
print(f"\nAnswer: sum_{{n=2}}^{{1000}} f(n) = {answer}")
# --- 4-Panel Visualization ---