原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=5608
题意
N 2 − 3 N + 2 = ∑ d ∣ N f ( d ) N^2-3N+2=\sum_{d|N}f(d) N2−3N+2=d∣N∑f(d)
计 算 ∑ i = 1 N f ( i ) 计算\sum_{i=1}^{N}f(i) 计算i=1∑Nf(i)
化简
先设一个函数
g ( N ) = N 2 − 3 N + 2 = ∑ d ∣ N f ( d ) g(N) =N^2-3N+2=\sum_{d|N}f(d) g(N)=N2−3N+2=d∣N∑f(d)
根据莫比乌斯反演中的约数反演定理
f
(
N
)
=
∑
d
∣
N
μ
(
N
d
)
g
(
d
)
f(N)=\sum_{d|N}\mu(\frac{N}{d})g(d)
f(N)=d∣N∑μ(dN)g(d)
原式得
∑ i = 1 N ∑ d ∣ i μ ( d ) g ( i d ) \sum_{i=1}^{N}\sum_{d|i}\mu(d)g(\frac{i}{d}) i=1∑Nd∣i∑μ(d)g(di)
= ∑ d = 1 N μ ( d ) ∑ i = 1 N / d g ( i ) =\sum_{d=1}^{N}\mu(d)\sum_{i=1}^{N/d}g(i) =d=1∑Nμ(d)i=1∑N/dg(i)
设 s u m ( N ) = ∑ i = 1 N g ( i ) 设sum(N)=\sum_{i=1}^{N}g(i) 设sum(N)=i=1∑Ng(i)
= ∑ d = 1 N μ ( d ) s u m ( N d ) =\sum_{d=1}^{N}\mu(d)sum(\frac{N}{d}) =d=1∑Nμ(d)sum(dN)
s u m 可 以 O ( 1 ) 计 算 出 来 , μ 用 杜 教 筛 处 理 一 下 前 缀 和 sum可以O(1)计算出来,\mu用杜教筛处理一下前缀和 sum可以O(1)计算出来,μ用杜教筛处理一下前缀和
Code
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define re register
typedef long long ll;
typedef pair<int, int> PII;
const int N = 1e6 + 10, M = 1e6 + 5, INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
ll prime[N], mu[N], k, inv2, inv6;
bool is_prime[N];
ll ksm(ll a, ll b) {
ll res = 1, base = a;
while (b) {
if (b & 1) res = res * base % MOD;
base = base * base % MOD;
b >>= 1;
}
return res;
}
ll sum1(ll n) {
return n * (n + 1) % MOD * (2 * n % MOD + 1) % MOD * inv6 % MOD;
}
ll sum2(ll n) {
return n * (n + 1) % MOD * inv2 % MOD;
}
ll sum(ll n) {
return (sum1(n) - 3 * sum2(n) % MOD + 2 * n % MOD + MOD) % MOD;
}
inline void init(int n) {
memset(is_prime, true, sizeof is_prime);
mu[1] = 1;
for (int i = 2; i < n; ++i) {
if (is_prime[i]) prime[++k] = i, mu[i] = -1;
for (int j = 1; j <= k && i * prime[j] < n; ++j) {
is_prime[i * prime[j]] = false;
if (i % prime[j] == 0) {
break;
} else {
mu[i * prime[j]] = -mu[i];
}
}
}
for (ll i = 1; i < n; ++i) mu[i] = (mu[i] + mu[i-1] + MOD) % MOD;
}
unordered_map<ll, ll> sum_mu;
inline ll GetSum_mu(ll n) {
if (n <= 1e6) return mu[n];
if (sum_mu[n]) return sum_mu[n];
ll ans = 1;
for (ll l = 2, r; l <= n; l = r + 1) {
r = min(n, n / (n / l));
ans = (ans - (r - l + 1) * GetSum_mu(n / l) % MOD + MOD) % MOD;
}
return sum_mu[n] = ans % MOD;
}
ll calc(ll n) {
ll ans = 0;
for (ll l = 1, r; l <= n; l = r + 1) {
r = min(n, n / (n / l));
ans = (ans + (GetSum_mu(r) - GetSum_mu(l-1) + MOD) % MOD * sum(n / l) % MOD) % MOD;
}
return ans;
}
void solve() {
init(N); inv2 = ksm(2, MOD-2); inv6 = ksm(6, MOD-2);
int T; cin >> T; while (T--) {
ll n; cin >> n;
cout << calc(n) << endl;
}
}
signed main() {
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
#ifdef ACM_LOCAL
freopen("input", "r", stdin);
freopen("output", "w", stdout);
#endif
solve();
}