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]; }
};| Sum | Block formula |
|---|---|
| () | block count times value; hyperbola: |
| , blocks with arithmetic series | |
| joint blocks: | |
| (gcd sum) | blocks with prefix sums of |
| value on : | |
| directly |
Proof: the harmonic lemma and the block end
For there are at most values of ; for , takes at most values. Since is non-increasing in , equal values form blocks. For : , so the block ends at . Joint blocks of two such functions end at the smaller of the two ends; there are of them. In
FloorValues, … each value equals for a unique small (since maps the block back), so indexing large values by is injective. Also , so recursions on these values stay inside the set.
Harmonic numbers
| 1 | 2 | 5 | 10 | 100 | 1000 | ||
|---|---|---|---|---|---|---|---|
| 1 | 1.5 | 2.283 | 2.929 | 5.187 | 7.485 | 14.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 ().
Proof: the bounds on
is decreasing, so for . Summing the left inequality over gives ; summing the right one over and adding gives . The sequence decreases () and is bounded below by , so it converges to a limit .
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};
}Proof: the floor-sum recursion
Reduction: , giving the two additive terms (negative are shifted up by multiples of the same way). Swap: with , the sum counts lattice points with and . Let ; counting by rows instead of columns, the points with a given are the with , i.e. , and after substituting the new index the count becomes the same kind of sum with as the loop does. Each round replaces by after the reduction, so there are rounds, and all intermediate values fit in 128 bits.
FGH: for , write and . Then , which is the swapped sum. For : . For : , so . Expressing these with the recursive triple (sums over of , , ) gives the three formulas; the reduction step expands and with , .