Harmonic lemma: takes at most distinct values for , and each value occupies one contiguous block . So any sum with prefix sums of costs . Floor sums follow a Euclid-like recursion in . Harmonic numbers explain why “for , loop over multiples of ” is .

Block iteration

ll sumFloorDiv(ll n) {                                     // sum_{i=1}^n floor(n / i) = sum_{k<=n} d(k)
    ll s = 0;
    for (ll l = 1, r; l <= n; l = r + 1) { r = n / (n / l); s += (r - l + 1) * (n / l); }
    return s;
}
ll sumMod(ll n, ll k) {                                    // sum_{i=1}^n (k mod i) = n k - sum i floor(k / i)
    i128 s = (i128)n * k;
    for (ll l = 1, r; l <= min(n, k); l = r + 1) { r = min(n, k / (k / l)); s -= (i128)(k / l) * (l + r) * (r - l + 1) / 2; }
    return (ll)s;
}
// all distinct values v = floor(n / i), with an O(1) index (the backbone of Lucy / Min_25 sieves)
struct FloorValues {
    ll n, sq; vector<ll> vals; vector<int> lo, hi;         // lo[v] for v <= sq, hi[n / v] for v > sq
    FloorValues(ll n) : n(n), sq((ll)sqrtl(n)) {
        while (sq * sq > n) sq--; while ((sq + 1) * (sq + 1) <= n) sq++;
        lo.assign(sq + 2, -1); hi.assign(sq + 2, -1);
        for (ll l = 1; l <= n; l = n / (n / l) + 1) { ll v = n / l; (v <= sq ? lo[v] : hi[n / v]) = sz(vals); vals.push_back(v); }
    }
    int id(ll v) const { return v <= sq ? lo[v] : hi[n / v]; }
};
SumBlock formula
()block count times value; hyperbola:
, blocks with arithmetic series
joint blocks:
(gcd sum)blocks with prefix sums of
value on :
directly

Harmonic numbers

125101001000
11.52.2832.9295.1877.48514.393

; . Consequences: (divisor lists, sieving over multiples, the “for , for multiple of ” loop, harmonic-step loops like for (j = i; j <= n; j += i)), and -type bounds stay . Expected values: records / cycles of random permutations (), coupon collector ().

Floor sums

counts lattice points under a line; reducing modulo and swapping the axes gives Euclid’s recursion on : .

ll floorSum(ll n, ll m, ll a, ll b) {                      // sum_{i=0}^{n-1} floor((a i + b) / m), m > 0, any sign a, b
    ll ans = 0;
    if (a < 0) { ll a2 = (a % m + m) % m; ans -= (ll)((i128)n * (n - 1) / 2 * ((a2 - a) / m)); a = a2; }
    if (b < 0) { ll b2 = (b % m + m) % m; ans -= n * ((b2 - b) / m); b = b2; }
    for (;;) {
        if (a >= m) { ans += (ll)((i128)n * (n - 1) / 2 * (a / m)); a %= m; }
        if (b >= m) { ans += n * (b / m); b %= m; }
        i128 yMax = (i128)a * n + b;
        if (yMax < m) break;
        n = (ll)(yMax / m); b = (ll)(yMax % m); swap(m, a);
    }
    return ans;
}

Generalised: with for , the triple , , follows the same recursion (all modulo a prime).

struct FGH { mint f, g, h; };
FGH floorFGH(ll a, ll b, ll c, ll n) {                     // a, b >= 0, c > 0, sums over i = 0..n
    mint N = n, s1 = N * (N + 1) / 2, s2 = N * (N + 1) * (2 * N + 1) / 6;
    if (a >= c || b >= c) {
        FGH t = floorFGH(a % c, b % c, c, n); mint A = a / c, B = b / c;
        return {t.f + A * s1 + B * (N + 1), t.g + A * s2 + B * s1,
                t.h + A * A * s2 + B * B * (N + 1) + A * B * 2 * s1 + B * 2 * t.f + A * 2 * t.g};
    }
    ll m = (ll)(((i128)a * n + b) / c);
    if (m == 0) return {0, 0, 0};
    FGH t = floorFGH(c, c - b - 1, a, m - 1); mint M = m;
    mint f = N * M - t.f;
    mint g = (M * N * (N + 1) - t.h - t.f) / 2;
    mint h = N * M * (M + 1) - t.g * 2 - t.f * 2 - f;
    return {f, g, h};
}