給 n, k (≤10⁹),求 S = Σ_{i=1}^{n} (k % i)。多行輸入直到 EOF。
對固定 k,k / i 只有 O(√k) 種不同取值。
對於給定商 q = k / i,i 的取值範圍為 [k/(q+1)+1, k/q]。
在該區間內,k % i = k - q * i,求和可用等差數列公式。
遍歷所有 q,累加區間和,總時間 O(√k)。
sum_mod(k, n) = Σ_{i=1}^{min(n,k)} (k % i)。Σ_{i=k+1}^{n} (k % i) = Σ_{i=k+1}^{n} k = k * (n - k)。i = 1 開始,當 i ≤ min(n,k):q * (i + last) * cnt / 2 其中 cnt = last - i + 1,但實際 k % i = k - q*i,所以區間和 = cnt * k - q * (i + last) * cnt / 2。#include <bits/stdc++.h>
using namespace std;
using int64 = long long;
int64 sum_mod(int64 k, int64 n) {
if (n <= 0) return 0;
int64 limit = min(n, k);
int64 res = 0;
for (int64 i = 1, last; i <= limit; i = last + 1) {
int64 q = k / i;
last = min(limit, q ? k / q : limit);
int64 cnt = last - i + 1;
// Σ (k - q*j) for j=i..last = cnt*k - q * (i+last)*cnt/2
res += cnt * k - q * (i + last) * cnt / 2;
}
if (n > k) res += k * (n - k); // i > k 時 k%i = k
return res;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int64 n, k;
while (cin >> n >> k) {
cout << sum_mod(k, n) << '\n';
}
return 0;
}
這是「除法分塊」的經典應用,將 O(n) 求和優化為 O(√n),廣泛用於數論求和問題。