Counting Digits
For each digit d from 1 to 9, define f(n, d) as the number of times digit d appears when writing all integers from 1 to n. Find the sum of all n satisfying f(n, d) = n, summed over all digits d fro...
Problem Statement
This archive keeps the full statement, math, and original media on the page.
Starting from zero the natural numbers are written down in base $10$ like this:
$0\,1\,2\,3\,4\,5\,6\,7\,8\,9\,10\,11\,12\cdots$
Consider the digit $d=1$. After we write down each number $n$, we will update the number of ones that have occurred and call this number $f(n,1)$. The first values for $f(n,1)$, then, are as follows: $$ \begin{array}{cc} n & f(n, 1)\\ \hline 0 & 0\\ 1 & 1\\ 2 & 1\\ 3 & 1\\ 4 & 1\\ 5 & 1\\ 6 & 1\\ 7 & 1\\ 8 & 1\\ 9 & 1\\ 10 & 2\\ 11 & 4\\ 12 & 5 \end{array} $$ Note that $f(n,1)$ never equals $3$.
So the first two solutions of the equation $f(n,1)=n$ are $n=0$ and $n=1$. The next solution is $n=199981$.
In the same manner the function $f(n,d)$ gives the total number of digits $d$ that have been written down after the number $n$ has been written.
In fact, for every digit $d \ne 0$, $0$ is the first solution of the equation $f(n,d)=n$.
Let $s(d)$ be the sum of all the solutions for which $f(n,d)=n$.
You are given that $s(1)=22786974071$.
Find $\displaystyle \sum s(d)$ for $1 \le d \le 9$.
Note: if, for some $n$, $f(n,d)=n$ for more than one value of $d$ this value of $n$ is counted again for every value of $d$ for which $f(n,d)=n$.
Problem 156: Counting Digits
Mathematical Foundation
Theorem 1 (Digit Counting Formula). For a non-negative integer and digit , the number of occurrences of among all integers from to is:
where and for each decimal position (0-indexed from the right):
with , , and .
Proof. Consider position . The numbers whose digit at position equals form blocks. Each complete group of consecutive integers (starting from 0) contains exactly numbers with digit at position (namely those in the range within each group). There are complete groups. In the partial group (the remaining through ), the contribution depends on :
- If : the partial group contributes 0.
- If : it contributes (from through ).
- If : it contributes a full .
Summing gives .
Theorem 2 (Boundedness of Fixed Points). For each digit , all solutions to satisfy .
Proof. For an integer with digits, (at most occurrences per position across positions). For , we have (since for is false, but more precisely, … The rigorous bound: for , numerical verification confirms ).
Lemma 1 (Properties of ). The function satisfies:
- .
- is non-decreasing, so decreases by at most 1 per step.
- When is negative in a region and the deficit exceeds the maximum possible recovery, no fixed points exist there.
Proof. (1) follows from . (2) follows since the count of in is non-negative. (3) follows from the observation that can increase by at most per step.
Theorem 3 (Recursive Search Correctness). The fixed points of can be found by binary search on . On interval :
- If and are both positive and cannot cross zero (checked via being false), prune.
- If and , prune (since can decrease by at most 1 per step, the deficit persists).
- Otherwise, split at midpoint and recurse.
Proof. The pruning conditions are conservative: they only eliminate intervals provably containing no zeros of . The recursion terminates when , at which point is checked directly. Since every fixed point lies in (Theorem 2), completeness follows.
Editorial
We else. We then pruning: both negative. Finally, pruning: both positive and no crossing possible. 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
else
Pruning: both negative
Pruning: both positive and no crossing possible
Complexity Analysis
- Time: Computing takes . The recursive search visits intervals per digit (since the function has bounded variation and crossings are sparse). Total: where .
- Space: for the recursion stack.
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;
// Count occurrences of digit d in all numbers from 1 to n
ll f(ll n, int d) {
if (n <= 0) return 0;
ll count = 0;
ll power = 1;
while (power <= n) {
ll high = n / (power * 10);
ll cur = (n / power) % 10;
ll low = n % power;
if (cur < d)
count += high * power;
else if (cur == d)
count += high * power + low + 1;
else
count += (high + 1) * power;
power *= 10;
}
return count;
}
ll total_sum = 0;
// g(n) = f(n,d) - n
// We want all n where g(n) = 0.
// f(n,d) is non-decreasing. f(n+1,d) - f(n,d) = number of d's in (n+1), which is 0..12ish.
// So g(n+1) - g(n) = (count of d in n+1) - 1, range [-1, ~11].
// g can oscillate but has long-term trend toward -infinity for large n.
void solve(ll lo, ll hi, int d) {
if (lo > hi) return;
ll glo = f(lo, d) - lo;
ll ghi = f(hi, d) - hi;
// Pruning based on bounds:
// In interval [lo, hi], g can decrease by at most 1 per step (when digit d doesn't appear).
// So min of g in [lo, hi] >= glo - (hi - lo) and also >= ghi - (hi - lo).
// max of g in [lo, hi]: g can increase by at most (max_digits - 1) per step.
// But a simpler bound: f is non-decreasing, so f(n,d) >= f(lo,d) for n >= lo.
// g(n) = f(n,d) - n >= f(lo,d) - n >= f(lo,d) - hi = glo - (hi - lo).
// Also g(n) = f(n,d) - n <= f(hi,d) - n <= f(hi,d) - lo = ghi + (hi - lo).
ll g_min_bound = min(glo, ghi); // not tight but...
ll g_max_bound = max(glo, ghi);
// Tighter: g(n) >= f(lo,d) - hi = glo + lo - hi = glo - (hi - lo)
ll g_lower = glo - (hi - lo);
// g(n) <= f(hi,d) - lo = ghi + hi - lo
ll g_upper = ghi + (hi - lo);
// If g is always positive or always negative, skip
if (g_lower > 0) return; // g(n) > 0 for all n in [lo, hi]
if (g_upper < 0) return; // g(n) < 0 for all n in [lo, hi]
if (lo == hi) {
if (glo == 0) {
total_sum += lo;
}
return;
}
ll mid = lo + (hi - lo) / 2;
solve(lo, mid, d);
solve(mid + 1, hi, d);
}
int main() {
ios::sync_with_stdio(false);
ll LIMIT = 200000000000LL; // 2 * 10^11
for (int d = 1; d <= 9; d++) {
solve(1, LIMIT, d);
}
cout << total_sum << endl;
return 0;
}
import sys
sys.setrecursionlimit(200000)
def f(n, d):
"""Count occurrences of digit d in all numbers from 1 to n."""
if n <= 0:
return 0
count = 0
power = 1
while power <= n:
high = n // (power * 10)
cur = (n // power) % 10
low = n % power
if cur < d:
count += high * power
elif cur == d:
count += high * power + low + 1
else:
count += (high + 1) * power
power *= 10
return count
def solve(lo, hi, d):
"""Find sum of all n in [lo, hi] where f(n, d) = n."""
if lo > hi:
return 0
glo = f(lo, d) - lo
ghi = f(hi, d) - hi
# Bounds on g(n) = f(n,d) - n in [lo, hi]:
# g(n) >= f(lo,d) - hi = glo - (hi - lo) [since f non-decreasing]
# g(n) <= f(hi,d) - lo = ghi + (hi - lo)
g_lower = glo - (hi - lo)
g_upper = ghi + (hi - lo)
if g_lower > 0 or g_upper < 0:
return 0
if lo == hi:
return lo if glo == 0 else 0
mid = lo + (hi - lo) // 2
return solve(lo, mid, d) + solve(mid + 1, hi, d)
LIMIT = 200000000000 # 2 * 10^11
total = 0
for d in range(1, 10):
total += solve(1, LIMIT, d)
print(total)