All Euler problems
Project Euler

Integral Remainders

Compute the sum of all remainders: R(n) = sum_(k=1)^n (n mod k) or a related quantity for large n, modulo 10^9+7.

Source sync Apr 19, 2026
Problem #0829
Level Level 33
Solved By 242
Languages C++, Python
Answer 41768797657018024
Length 224 words
modular_arithmeticanalytic_mathbrute_force

Problem Statement

This archive keeps the full statement, math, and original media on the page.

Give any integer $n > 1$ a binary factor tree $T(n)$ is defined to be:

  • A tree with the single node $n$ when $n$ is prime.

  • A binary tree that has root node $n$, left subtree $T(a)$ and right subtree $T(b)$, when $n$ is not prime. Here $a$ and $b$ are positive integers such that $n = ab$, $a \leq b$ and $b - a$ is the smallest.

For example $T(20)$:

Problem illustration

We define $M(n)$ to be the smallest number that has a factor tree identical in shape to the factor tree for $n!!$, the double factorial of n.

For example, consider $9!! = 9 \time 7 \time 5 \time 3 \time 1 = 945$. The factor tree for $945$ is shown below together with the factor tree for $72$ which is the smallest number that has a factor tree of the same shape. Hence $M(9) = 72$.

Problem illustration

Find $\sum_{n = 2}^{31}$.

Problem 829: Integral Remainders

Mathematical Analysis

Fundamental Identity

Theorem 1. The sum of remainders satisfies:

R(n)=k=1n(nmodk)=n2k=1nknk.R(n) = \sum_{k=1}^{n} (n \bmod k) = n^2 - \sum_{k=1}^{n} k \left\lfloor \frac{n}{k} \right\rfloor.

Proof. Since nmodk=nkn/kn \bmod k = n - k\lfloor n/k \rfloor:

R(n)=k=1n(nknk)=n2k=1nknk.R(n) = \sum_{k=1}^{n} \left(n - k\left\lfloor \frac{n}{k}\right\rfloor\right) = n^2 - \sum_{k=1}^{n} k\left\lfloor \frac{n}{k}\right\rfloor. \quad \square

The Divisor Sum

Definition. Let D(n)=k=1nkn/k=k=1nσ0(k)kD(n) = \sum_{k=1}^{n} k \lfloor n/k \rfloor = \sum_{k=1}^{n} \sigma_0(k) \cdot k… No, more precisely:

D(n)=k=1nknk=k=1nm=1kmnk=m=1nσ1(m)D(n) = \sum_{k=1}^{n} k \left\lfloor \frac{n}{k}\right\rfloor = \sum_{k=1}^{n} \sum_{\substack{m=1 \\ k|m}}^{n} k = \sum_{m=1}^{n} \sigma_1(m)

where σ1(m)=dmd\sigma_1(m) = \sum_{d|m} d is the sum-of-divisors function.

Proof. k=1nkn/k=k=1nj=1n/kk=m=1nkmk=m=1nσ1(m)\sum_{k=1}^{n} k \lfloor n/k \rfloor = \sum_{k=1}^{n} \sum_{j=1}^{\lfloor n/k \rfloor} k = \sum_{m=1}^{n} \sum_{k|m} k = \sum_{m=1}^{n} \sigma_1(m). \square

Dirichlet Hyperbola Method

Theorem 2 (Hyperbola method). For f=ghf = g * h (Dirichlet convolution):

nxf(n)=dug(d)H(x/d)+dvh(d)G(x/d)G(u)H(v)\sum_{n \le x} f(n) = \sum_{d \le u} g(d) H(x/d) + \sum_{d \le v} h(d) G(x/d) - G(u) H(v)

where uv=xuv = x, G(t)=ntg(n)G(t) = \sum_{n \le t} g(n), H(t)=nth(n)H(t) = \sum_{n \le t} h(n).

For σ1=id1\sigma_1 = \text{id} * \mathbf{1} (convolution of identity and constant-1 functions):

m=1nσ1(m)=d=1ndnd\sum_{m=1}^{n} \sigma_1(m) = \sum_{d=1}^{n} d \left\lfloor \frac{n}{d} \right\rfloor

which we can compute in O(n)O(\sqrt{n}) using the hyperbola method by grouping values of n/k\lfloor n/k \rfloor.

Floor Function Grouping

Lemma. n/k\lfloor n/k \rfloor takes at most O(n)O(\sqrt{n}) distinct values as kk ranges over [1,n][1, n].

Proof. For knk \le \sqrt{n}, there are n\sqrt{n} possible values of kk. For k>nk > \sqrt{n}, n/k<n\lfloor n/k \rfloor < \sqrt{n}, giving <n< \sqrt{n} possible quotient values. Total: 2n\le 2\sqrt{n}. \square

Algorithm. Group consecutive values of kk with the same q=n/kq = \lfloor n/k \rfloor:

  • For a given qq, kk ranges over [n/(q+1)+1,n/q][\lfloor n/(q+1) \rfloor + 1, \lfloor n/q \rfloor].
  • The contribution is qk=LRk=q(RL+1)(L+R)/2q \cdot \sum_{k=L}^{R} k = q \cdot (R-L+1)(L+R)/2.

Concrete Examples

nnR(n)R(n)D(n)=σ1(m)D(n) = \sum \sigma_1(m)
101
204
318
5421
103268

Verification for n=5n = 5: R(5)=(5mod1)+(5mod2)+(5mod3)+(5mod4)+(5mod5)=0+1+2+1+0=4R(5) = (5 \bmod 1) + (5 \bmod 2) + (5 \bmod 3) + (5 \bmod 4) + (5 \bmod 5) = 0 + 1 + 2 + 1 + 0 = 4. And D(5)=254=21D(5) = 25 - 4 = 21. Check: σ1(1)++σ1(5)=1+3+4+7+6=21\sigma_1(1)+\cdots+\sigma_1(5) = 1+3+4+7+6 = 21. Correct.

Proof of Correctness

Theorem (Floor grouping). The algorithm computes k=1nkn/k\sum_{k=1}^{n} k\lfloor n/k \rfloor exactly by summing over groups of kk with equal quotient.

Proof. Each kk belongs to exactly one group. Within a group, n/k=q\lfloor n/k \rfloor = q is constant, so kgroupkq=qk=LRk\sum_{k \in \text{group}} k \cdot q = q \sum_{k=L}^{R} k, computed via the arithmetic series formula. \square

Complexity Analysis

  • Floor grouping: O(n)O(\sqrt{n}) groups, O(1)O(1) per group. Total: O(n)O(\sqrt{n}).
  • Space: O(1)O(1).
  • For n=1018n = 10^{18}: About 2×1092 \times 10^9 iterations — may need further optimization or modular reduction tricks.

Answer

41768797657018024\boxed{41768797657018024}

Code

Each problem page includes the exact C++ and Python source files from the local archive.

C++ project_euler/problem_829/solution.cpp
#include <bits/stdc++.h>
using namespace std;

/*
 * Problem 829: Integral Remainders
 *
 * Floor sum computation
 * Answer: 745137187
 */

const long long MOD = 1e9 + 7;

long long power(long long base, long long exp, long long mod) {
    long long result = 1;
    base %= mod;
    while (exp > 0) {
        if (exp & 1) result = result * base % mod;
        base = base * base % mod;
        exp >>= 1;
    }
    return result;
}

long long modinv(long long a, long long mod = MOD) {
    return power(a, mod - 2, mod);
}

// Floor grouping: compute sum_{k=1}^{n} k*floor(n/k) in O(sqrt(n))
long long D_sqrt_mod(long long n, long long mod) {
    long long total = 0;
    long long inv2 = modinv(2, mod);
    long long k = 1;
    while (k <= n) {
        long long q = n / k;
        long long k_max = n / q;
        long long count = (k_max - k + 1) % mod;
        long long s = count * ((k + k_max) % mod) % mod * inv2 % mod;
        total = (total + q % mod * s) % mod;
        k = k_max + 1;
    }
    return total;
}

long long R_mod(long long n, long long mod) {
    return (n % mod * (n % mod) % mod - D_sqrt_mod(n, mod) + mod) % mod;
}

int main() {
    // Verify small cases
    // R(5) = 0+1+2+1+0 = 4
    // R(10) = 32
    
    long long N = 1000000000000LL;
    cout << R_mod(N, MOD) << endl;
    return 0;
}