計算 J(n, k) = Σ_{i=1..n} (k mod i)。n, k ≤ 10^9,需 O(√k) 算法。
k mod i = k - i * ⌊k/i⌋。若 n > k,對於 i > k,k mod i = k,直接加 (n-k)*k,再處理 i=1..k。令 n = min(n, k)。
⌊k/i⌋ 只有 O(√k) 種不同取值。對於相同商 q = ⌊k/i⌋ 的連續區間 [L, R],余數形成等差數列:
k mod i = k - q*i (i 從 L 到 R 遞減 q) 首項 = k - q*L, 末項 = k - q*R, 項數 = R-L+1 區間和 = (首項+末項)*項數/2 = (2k - q(L+R))*(R-L+1)/2
給定當前 L 和商 q,最大 R 滿足 ⌊k/R⌋ = q。二分 R ∈ [L, n]。
typedef long long ll;
ll n, k, ans;
ll findR(ll L, ll q) { // 找最大 R 使 k/R == q
ll l = L, r = n;
while (l < r) {
ll mid = (l + r + 1) >> 1;
if (k / mid == q) l = mid;
else r = mid - 1;
}
return l;
}
int main() {
scanf("%lld%lld", &n, &k);
if (n > k) { ans += (n - k) * k; n = k; }
ll L = 1;
while (L <= n) {
ll q = k / L;
ll R = findR(L, q);
ans += (2*k - q*(L+R)) * (R - L + 1) / 2;
L = R + 1;
}
printf("%lld\n", ans);
return 0;
}
O(√k)。O(log n),總體 O(√k log k),k=10^9 约 6萬次操作,極快。k mod i = k - i*⌊k/i⌋ 轉化為商的分塊求和。