an accidentally novel combinatorics proof

2026-05-25

disclaimer

i did not touch any generative ai or agentic llm tools prior to february 2026. i had tried them many times over the years, and i always kept running into the same frustrations. this vehemently fueled my contrarian attitudes towards llms. while i still largely hold these attitudes, it is increasingly more difficult to deny the utility of these tools.

all written opinions are my own.

motivations

for the past few weeks, i have been doing a little r&d on a maths harness that uses claude code.

its maiden voyage was in a review of Go's new floating point parsing and printing algorithm where i tested its ability to function as an aide when reading reading Russ' proofs. in doing so, i uncovered a material edge case that diverged from the proof.

over the weekend, a friend showed me a tweet about AlphaProof's recent publications. my brain lit up; i asked my friend to just show me one of the titles. this was a great opportunity to benchmark my little project with only one clear bias: i knew that whatever it was, it was almost certainly provable.

set up

one program i have been tinkering on recently is a computational framework in Go that allows an agent to guess at how difficult a proof may be. the classifications are ternary:

the only problem i had formally pointed it at was an erdos problem that was deemed 'hard' by the framework; after running it on a051293, it deemed the problem 'elementary,' which is a bit funny.

i do not have the ability to concisely and neatly present the topics in my own voice; therefore, i have marked the sections [gen]erated by claude from the lean proof.

if i have time to review and understand these topics more deeply, i will revise this in a follow up. my understanding is that the premise of the proof is expressed correctly, and the lack of any axiom or sorry in the lean proof indicate that it is computationally verified.

my process was largely hands-off; i spent a majority of active time thinking about the meta strategy and documenting frictions the harness experienced and was incapable of self-documenting. i did interject a few key details that are otherwise not noteworthy when compared to how claude materialized them.

the theorem

in 2002, Cloitre conjectured that the number of nonempty subsets of {1,...,n} with integer mean satisfies

a(n)=2n+1nk=0MF(k)nk+o(2nnM+1)

for all M, where F(k) are exactly the ordered Bell Numbers:

{1,1,3,13,75,541,}

the proof decomposes into three independent modules sketched below for brevity.

module a: counting with frequencies [gen]

the first task is counting subsets of {1,...,k} whose elements sum to 0modk. this is a discrete fourier transform on cyclic groups.

the roots of unity filter [gen]

let ζ be a primitive k-th root of unity. character orthogonality gives

r=0k-1ζrn={kif kn0otherwise

applying this to indicator-sum over all subsets S{1,,k}:

b(k):
    zeta = primitive k-th root of unity
    total = 0
    for r in {0, ..., k-1}:
        total += product over m in {1,...,k} of (1 + zeta^(r*m))
    return total / k

the product m=1k(1+ζrm) expands via Finset.prod_add into exactly S{1,,k}ζrsum(S). averaging over r applies the orthogonality filter, extracting the count of subsets with ksum(S).

evaluating the product [gen]

for a given r, the values ζrm for m=1,,k cycle through the q-th roots of unity with multiplicity k/q, where q=k/gcd(r,k). the product reduces to

(j=0q-1(1+ωj))k/q

where ω is a primitive q-th root of unity. evaluating xq-1=j(x-ωj) at x=-1 gives (-1)q-1=j(-1-ωj). factoring out (-1)q:

j=0q-1(1+ωj)={2q odd0q even

collecting by gcd [gen]

for each divisor d of k, exactly φ(k/d) values of r{0,,k-1} satisfy gcd(r,k)=d. the corresponding q=k/d contributes 2d when k/d is odd (i.e., d is an odd divisor of k) and 0 otherwise. summing:

b(k)=1kdkd oddφ(d)2k/d

this is stanley's exercise 1.105. the lean proof uses IsPrimitiveRoot, Polynomial.nthRootsFinset, and Nat.totient.

module b: the Zumkeller identity [gen]

this module proves the per-k identity connecting two counts:

the claim is L(k)=R(k). this was observed without proof by Zumkeller (2006, oeis a082550) and Wiseman (2019, oeis a063776). as of may 2026, no proof exists in the published literature. to the best of my knowledge, the proof below is the first.

setup [gen]

work in {0,,k-1} (representing {1,,k} shifted by 1). for a nonempty subset S, define

α(k,S)=|{r{0,,k-1}:k(σ+r|S|)}| β(k,S)=|{j{0,,|S|-1}:|S|(σ+kj)}|

where σ=sS(s+1).

the key lemma [gen]

α=β

both α and β count solutions to a linear congruence of the form m(b+ax) over x{0,,m-1}. the solution count is:

count_solutions(b, a, m):
    g = gcd(a, m)
    if g divides b: return g
    else:           return 0

α has (a,m)=(|S|,k); β has (a,m)=(k,|S|). since gcd(|S|,k)=gcd(k,|S|) and the divisibility condition on b=σ is the same, α(k,S)=β(k,S) for every nonempty S.

another lemma [gen]

α=kL(k)

define rotate(S,r)={(s+r)modk:sS}. rotation preserves cardinality and is a bijection on the powerset of {0,,k-1}.

the divisibility condition rewrites as: k(σ+r|S|) iff ksum(rotate(S,r)), where the sum uses the (s+1)-shift convention. so α(k,S) counts exactly how many of S's k rotations land in the set {T:ksum(T)}.

swapping summation order --- sum over r first, then over S --- each rotation r is a bijection on nonempty subsets, so each r contributes L(k). but the set counted by L(k) excludes (which always satisfies the divisibility), so:

Sα(k,S)=kL(k)

yet another lemma [gen]

β=kR(k)

β(k,S) admits a host-element decomposition: rewrite it as the number of elements eS such that |S|(σ+krank(e,S)), where rank(e,S)=|{sS:s<e}|.

define hostSet(k,e)={S:eS, |S|(σ+krank(e,S))}. swapping the sum over S with the sum over e{0,,k-1}:

Sβ(k,S)=e=0k-1|hostSet(k,e)|

the key structural fact is that rotation by 1 bijects hostSet(k,e) onto hostSet(k,(e+1)modk). the forward direction (rotation preserves membership and divisibility, shifting the host element) is proved by case analysis on whether e=k-1 (wrapping) or e<k-1 (no wrapping). the backward direction uses rotation by k-1. since rotation gives in both directions, equality holds:

|hostSet(k,e)|=|hostSet(k,0)| e

finally, a reflection bijection sk-1-s establishes |hostSet(k,0)|=R(k). reflection maps element 0 to element k-1 (the representation of k in the shifted indexing) and preserves the divisibility condition since sum(reflect(S))+sum(S)=(k+1)|S|.

therefore:

Sβ(k,S)=kR(k)

the identity [gen]

α=β term-by-term implies kL(k)=kR(k). dividing by k:

L(k)=R(k) k1

module c: the discrete laplace method [gen]

the d = 1 term in b(k) contributes 2k/k. every odd divisor d3 contributes at most 2k/3d/k, since k/dk/3 and φ(d)<d. summing this tail over k=1,,n gives O(n22n/3), which is o(2n/nM+1) for any M. so

a(n)=S(n)-n+o(2n/nM+1), S(n)=k=1n2kk

reindexing [gen]

substituting j=n-k:

S(n)=2nj=0n-112j(n-j)

the 1/2j factor ensures the sum is dominated by small j.

geometric expansion [gen]

the standard identity for a geometric partial sum gives

1n-j=1ni=0M(jn)i+(j/n)M+1n-j

substituting and exchanging the finite sums (j first, then i):

S(n)=2nni=0M1nij=0n-1ji2j + 2nj=0n-1(j/n)M+12j(n-j)

the remainder term is o(1/nM+1) after splitting the j-sum at n/2: the low half is bounded by the polylogarithmic tsum, the high half decays as O(1/2n/2).

the coefficient identity [gen]

the inner partial sum converges to the polylogarithmic series:

j=0jm2j=2F(m)

proved by strong induction on m. the base case m=0 is the geometric series

1/2j=2

for the inductive step, the shift identity

(j+1)m/2j=2jm/2j

is valid for m1, and when combined with the binomial expansion

(j+1)m+1-jm+1=k<m+1(m+1k)jk

and the fubini recurrence

F(m+1)=k=0m(m+1k)F(k)

the value pins.

error budget [gen]

source bound absorbed by
non-dominant divisors O(n22n/3) o(2n/nM+2)
geometric remainder O(1/nM+2) after ×2n o(2n/nM+1)
partial-sum truncation O(ni/2n) per coefficient o(1/n) after ×2n/n

all three are o(2n/nM+1).

the bridge [gen]

a051293_counting.lean links the three modules:

// module A: the DFT formula matches the combinatorial count
b_comb_eq_b(k):    b_comb(k) == b(k)    for all k >= 1

// module B: per-k identity via Zumkeller
zumkeller_identity(k):    b_comb(k) - 1 == |maxKIntMeanSubsets(k)|

// summation: partition integer-mean subsets by max element
a_comb_eq_sum(n):    a_comb(n) == sum_{k=1}^{n} (b_comb(k) - 1)

// bridge: combinatorial count equals analytic formula
a_comb_eq_a(n):    a_comb(n) == a(n)    for all n >= 1

// module C: asymptotic expansion of a(n)
asymptotic_expansion(M):    a(n) = fubini_expansion + o(2^n/n^{M+1})

composing a_comb_eq_a with asymptotic_expansion yields the final theorem:

cloitre_conjecture(M):
    a_comb(n) = (2^{n+1}/n) * sum_{i=0}^{M} F(i)/n^i
              + o(2^n / n^{M+1})

closing thoughts

from start to finish, it took approximately 6 hours and a few fresh sessions to grok the proof. i suspect that much of this time can be greatly reduced with better tooling which i am actively working on.

as far as the results, module a and module c are what i believe would be called "standard analysis."

module b is new as far as i am aware. the identity was observed empirically by Zumkeller in 2006 and restated by Wiseman in 2019. no proof, formal or informal, appears anywhere in the published literature or obvious websites. the lean formalization i "wrote" is the first to my knowledge.

additionally, these results appear to be fundamentally different in at least two ways to those published by AlphaProof Nexus.

the lean source code for the proof can be found on my github.