定義 f(n) = Σ_{i=1..n} ⌊n/i⌋。求 sum(a,b) = Σ_{n=a..b} f(n) mod 1007。多組查詢(≤10000),a,b ≤ 1,000,000。
f(n) 等價於滿足 x*y ≤ n 的正整數對 (x,y) 的個數。定義 g(n) = 滿足 x*y = n 的對數(即 n 的約數個數)。則 f(n) = Σ_{k=1..n} g(k),即 g 的前綴和。進而 sum(a,b) = Σ_{n=a..b} f(n) 是 f 的前綴和,即 g 的二階前綴和。
g[i] = 0。對每個 i=1..1e6,對其倍數 j=i, 2i, ... 做 g[j]++。這等價於計算每個數的約數個數,複雜度 O(N log N)。f[i] = (f[i-1] + g[i]) % MOD。sum[i] = (sum[i-1] + f[i]) % MOD。(sum[b] - sum[a-1] + MOD) % MOD。#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const int MAXN = 1000000;
const int MOD = 1007;
int g[MAXN+1];
int f[MAXN+1];
int sum[MAXN+1];
void init() {
memset(g, 0, sizeof(g));
for (int i = 1; i <= MAXN; i++)
for (int j = i; j <= MAXN; j += i)
g[j]++;
for (int i = 1; i <= MAXN; i++) {
f[i] = (f[i-1] + g[i]) % MOD;
sum[i] = (sum[i-1] + f[i]) % MOD;
}
}
int main() {
init();
int a, b;
while (scanf("%d%d", &a, &b) == 2) {
int ans = (sum[b] - sum[a-1] + MOD) % MOD;
printf("%d\n", ans);
}
return 0;
}
本題核心是將 ⌊n/i⌋ 求和轉化為約數個數統計,利用篩法 O(N log N) 預處理所有 g(n),再做兩次前綴和即可 O(1) 回答查詢。體現了「數論函數前綴和 + 篩法」的通用技巧。