Factors of Two in Binomial Coefficients
Define g(n, m) as the largest integer k such that 2^k | C(n, m). Let F(n) = max{g(n, m): 0 <= m <= n} and S(N) = sum_(n=1)^N F(n). Given F(10) = 3, F(100) = 6, S(100) = 389, S(10^7) = 203,222,840,...
Problem Statement
This archive keeps the full statement, math, and original media on the page.
Define \(g(n, m)\) to be the largest integer \(k\) such that \(2^k\) divides \(\binom {n}m\). For example, \(\binom {12}5 = 792 = 2^3 \cdot 3^2 \cdot 11\), hence \(g(12, 5) = 3\). Then define \(F(n) = \max \{ g(n, m) : 0 \le m \le n \}\). \(F(10) = 3\) and \(F(100) = 6\).
Let \(S(N)\) = \(\displaystyle \sum _{n=1}^N{F(n)}\). You are given that \(S(100) = 389\) and \(S(10^7) = 203222840\).
Find \(S(10^{16})\).
Problem 704: Factors of Two in Binomial Coefficients
Mathematical Foundation
Theorem 1 (Kummer, 1852). The -adic valuation equals the number of carries when adding and in base .
Proof. By Legendre’s formula, . Therefore
Each summand equals the carry out of position when adding and in base . This is Kummer’s classical result.
Theorem 2 (Maximum 2-adic Valuation). For ,
where is the 2-adic valuation of (the exponent of 2 in the factorization of ).
Proof. Write in binary as where and . Let , so bits and .
By Kummer’s theorem, counts the carries in in binary. A carry at position occurs when , where is the incoming carry.
Upper bound: The total number of carries is at most . Position is the lowest 1-bit of . At positions , we have , so must produce digit . If there is an incoming carry, the outgoing carry simply propagates but does not create a “net” carry. The bit at position is the highest bit and cannot generate a carry out. Hence at most positions can contribute carries.
Achievability: Choose such that in binary addition , carries are generated at every position from through . For example, take (a specific construction that maximizes carry chain length). This produces exactly carries.
Lemma 1 (Summation Decomposition). , where
Proof. Immediate from and linearity of summation.
Lemma 2 (Closed Form for ). Let . Then
Proof. For , the integers with are , contributing . The remaining integers contribute . Thus:
The identity follows by differentiating the geometric series and substituting .
Lemma 3 (Closed Form for ).
Proof. Each integer contributes to . The value iff , so , which terminates at .
Editorial
We compute A(N). Finally, compute B(N). We enumerate the admissible parameter range, discard candidates that violate the derived bounds or arithmetic constraints, and update the final set or total whenever a candidate passes the acceptance test.
Pseudocode
Compute A(N)
Compute B(N)
Complexity Analysis
- Time: , since the loop runs iterations and all arithmetic is (with big-integer support for ).
- Space: .
Answer
Code
Each problem page includes the exact C++ and Python source files from the local archive.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef __int128 lll;
int main() {
ll N = 10000000000000000LL; // 10^16
// S(N) = sum_{n=1}^{N} F(n)
// F(n) = floor(log2(n)) - v2(n)
// S(N) = A(N) - B(N)
// A(N) = sum of floor(log2(n)) for n=1..N
// B(N) = sum of v2(n) for n=1..N
// Compute A(N) = sum of floor(log2(n)) for n=1..N
int B = 63 - __builtin_clzll(N); // floor(log2(N))
// sum_{b=0}^{B-1} b * 2^b = (B-2)*2^B + 2
// Plus B * (N - 2^B + 1) for numbers from 2^B to N
// Use __int128 to avoid overflow
lll powerB = (lll)1 << B;
lll A = (lll)(B - 2) * powerB + 2 + (lll)B * ((lll)N - powerB + 1);
// Compute B(N) = sum_{k=1}^{inf} floor(N/2^k)
lll Bval = 0;
for (int k = 1; k <= B; k++) {
Bval += (lll)N >> k;
}
lll result = A - Bval;
// Print __int128
ll r = (ll)result;
cout << r << endl;
return 0;
}
#!/usr/bin/env python3
"""Project Euler Problem 704: Factors of Two in Binomial Coefficients"""
def solve():
N = 10**16
# F(n) = floor(log2(n)) - v2(n) where v2(n) is 2-adic valuation
# S(N) = sum F(n) for n=1..N = A(N) - B(N)
# A(N) = sum of floor(log2(n)) for n=1..N
B = N.bit_length() - 1 # floor(log2(N))
powerB = 1 << B
# sum_{b=0}^{B-1} b * 2^b = (B-2)*2^B + 2
A = (B - 2) * powerB + 2 + B * (N - powerB + 1)
# B(N) = sum of v2(n) for n=1..N = sum_{k>=1} floor(N/2^k)
Bval = 0
for k in range(1, B + 1):
Bval += N >> k
result = A - Bval
print(result)
# Verify with small cases
def F(n):
if n == 0:
return 0
return (n.bit_length() - 1) - (n & -n).bit_length() + 1
def S_brute(N):
return sum(F(n) for n in range(1, N + 1))
# Check S(100)
print(f"S(100) = {S_brute(100)} (expected 389)")
print(f"S(10^7) check with formula:")
# Formula check for N=100
B100 = 99 .bit_length() - 1 # Actually need bit_length of 100
B100 = (100).bit_length() - 1
p100 = 1 << B100
A100 = (B100 - 2) * p100 + 2 + B100 * (100 - p100 + 1)
Bval100 = sum(100 >> k for k in range(1, B100 + 1))
print(f"Formula S(100) = {A100 - Bval100} (expected 389)")
solve()