Binomial Coefficient Divisibility
Find the number of entries in Pascal's triangle (rows 0 through N = 1000) that are not divisible by the prime p = 2.
Problem Statement
This archive keeps the full statement, math, and original media on the page.
A
Let us define the
For example, \(20\) has roundness \(2\) in base \(2\), because the base \(2\) representation of \(20\) is \(10100\), which ends with \(2\) zeros.
Also define \(R(n)\), the
For example, \(20\) has roundness \(2\) in base \(2\) and roundness \(1\) in base \(4\), \(5\), \(10\), \(20\), hence we get \(R(20)=6\).
You are also given \(R(10!) = 312\).
Find \(R(10\,000\,000!)\). Give your answer modulo \(10^9 + 7\).
Problem 926: Binomial Coefficient Divisibility
Mathematical Foundation
Theorem 1 (Lucas’ Theorem, 1878). Let be a prime and let be non-negative integers with base- representations and . Then
Proof. We use the Frobenius endomorphism: in , . By induction, . Writing :
The coefficient of on the left is . On the right, writing and using the uniqueness of base- representation, the coefficient of is . (Cross-terms from different -positions cannot combine to give the same power of because of the uniqueness of base- digits.)
Theorem 2 (Non-divisibility Criterion). if and only if for every digit position in base .
Proof. From Theorem 1, . Since , each factor is nonzero mod iff (as for and for ). The product is nonzero iff every factor is nonzero.
Theorem 3 (Per-Row Count). The number of entries () not divisible by equals
where in base .
Proof. By Theorem 2, we need to count with for each . Since the digits are independent, the count is .
Lemma 1 (Specialization to ). For , each digit , so , and the number of odd entries in row is , where is the number of 1-bits.
Proof. When , the factor is 1; when , the factor is 2. The product is .
Theorem 4 (Kummer’s Theorem, 1852). The largest power of dividing equals the number of carries when adding and in base .
Proof. By Legendre’s formula, . Then
Each term equals the carry into position when adding and in base .
Editorial
Optimized digit DP for general . We use dynamic programming over the state space implied by the derivation, apply each admissible transition, and read the answer from the final table entry.
Pseudocode
Compute base-p digits of N
S(p^k - 1) = ((p+1)/2)^k for p=2: number of non-zero entries in rows 0..p^k-1
General: product_{digit positions} sum over digit values of (d+1)
Contribution from rows with digit_i < d at position i
and arbitrary lower digits (within full range 0..p-1)
Complexity Analysis
- Time (brute force): — iterating over rows and computing popcount.
- Time (digit DP): .
- Space: for digit representation.
Answer
Code
Each problem page includes the exact C++ and Python source files from the local archive.
#include <bits/stdc++.h>
using namespace std;
/*
* Problem 926: Binomial Coefficient Divisibility
*
* Count entries in Pascal's triangle (rows 0-1000) NOT divisible by p=2.
*
* By Lucas' theorem: binom(n,k) != 0 mod p iff each base-p digit
* of k <= corresponding digit of n.
* Non-zero entries in row n = prod(d_i + 1) over base-p digits d_i.
* For p=2: = 2^popcount(n).
*
* Kummer's theorem: v_p(binom(m+n,m)) = # carries adding m,n in base p.
*
* Complexity: O(N * log_p(N)).
*/
int main() {
int N = 1000, p = 2;
long long total = 0;
for (int n = 0; n <= N; n++) {
long long prod = 1;
int nn = n;
if (nn == 0) { total += 1; continue; }
while (nn > 0) {
prod *= (nn % p + 1);
nn /= p;
}
total += prod;
}
cout << total << endl;
// Verify: row 0 has 1 entry, row 1 has 2, row 3 has 4
assert(1 == 1); // row 0
// row 3 = 11 in binary, popcount=2, so 2^2=4 odd entries
int r3 = 1;
int nn = 3;
while (nn > 0) { r3 *= (nn%2+1); nn /= 2; }
assert(r3 == 4);
return 0;
}
"""
Problem 926: Binomial Coefficient Divisibility
Count non-zero entries mod p in Pascal's triangle rows 0..N. For each row n,
the number of entries C(n,k) not divisible by p equals the product of (d_i + 1)
where d_i are the base-p digits of n (Kummer's theorem / Lucas' theorem).
Key ideas:
- By Lucas' theorem, C(n,k) != 0 mod p iff each base-p digit of k <= digit of n.
- Number of non-zero entries in row n = product of (d_i + 1) for base-p digits d_i.
- For p=2, this equals 2^(popcount(n)), giving a self-similar fractal structure.
- Sierpinski triangle pattern emerges in Pascal's triangle mod 2.
Methods:
1. Digit-product formula (Lucas' theorem application)
2. Direct binomial computation for small cases (verification)
3. Fractal dimension analysis
4. Comparison across different primes
"""
import numpy as np
from math import comb
def count_nonzero_row(n, p):
"""Count entries in row n of Pascal's triangle not divisible by p."""
prod = 1
while n > 0:
prod *= (n % p + 1)
n //= p
return prod
def solve(N=1000, p=2):
"""Sum of non-zero-mod-p entries across rows 0..N."""
total = 0
for n in range(N + 1):
total += count_nonzero_row(n, p)
return total
def count_nonzero_row_brute(n, p):
"""Count entries in row n not divisible by p by direct computation."""
count = 0
for k in range(n + 1):
if comb(n, k) % p != 0:
count += 1
return count
def fractal_dimension_estimate(p, max_power=10):
"""Estimate fractal dimension: total non-zero entries up to p^k rows.
For Pascal mod p, the fractal dimension is log(p*(p+1)/2) / log(p).
"""
ratios = []
for k in range(2, max_power + 1):
N = p**k
total = sum(count_nonzero_row(n, p) for n in range(N))
if k > 2:
prev_N = p**(k - 1)
prev_total = sum(count_nonzero_row(n, p) for n in range(prev_N))
ratios.append(np.log(total / prev_total) / np.log(p))
return ratios
def row_counts_for_prime(N, p):
"""Return list of non-zero entry counts per row for given prime."""
return [count_nonzero_row(n, p) for n in range(N)]
# Solve and verify
answer = solve()
# Verify digit-product formula against brute force for small cases
for n in range(50):
assert count_nonzero_row(n, 2) == count_nonzero_row_brute(n, 2), f"Mismatch at row {n}"
# Verify for p=3
for n in range(40):
assert count_nonzero_row(n, 3) == count_nonzero_row_brute(n, 3), f"Mismatch at row {n} for p=3"
# Known: row 2^k - 1 has all entries odd (all 2^k entries are odd)
for k in range(1, 8):
n = 2**k - 1
assert count_nonzero_row(n, 2) == 2**k
print(answer)