因为
d
(
i
j
)
=
∑
p
∣
i
∑
q
∣
i
[
(
p
,
q
)
=
=
1
]
p
j
q
d(ij) = \sum_{p | i} \sum_{q | i} [(p, q) == 1] \frac{pj}{q}
d(ij)=∑p∣i∑q∣i[(p,q)==1]qpj
那么
∑
i
=
1
n
∑
j
=
1
n
d
(
i
∗
j
)
\sum_{i = 1}^n \sum_{j = 1}^n d(i * j)
i=1∑nj=1∑nd(i∗j)
=
∑
i
=
1
n
∑
j
=
1
n
∑
p
∣
i
∑
q
∣
i
[
(
p
,
q
)
=
=
1
]
p
j
q
= \sum_{i = 1}^n \sum_{j = 1}^n \sum_{p | i} \sum_{q | i} [(p, q) == 1] \frac{pj}{q}
=i=1∑nj=1∑np∣i∑q∣i∑[(p,q)==1]qpj
对式子大力莫反,有
=
∑
d
=
1
n
μ
[
d
]
∑
i
=
1
n
∑
j
=
1
n
∑
p
∣
i
∑
q
∣
i
[
d
∣
(
p
,
q
)
]
p
j
q
= \sum_{d = 1}^n \mu[d] \sum_{i = 1}^n \sum_{j = 1}^n \sum_{p | i} \sum_{q | i} [d | (p, q)] \frac{pj}{q}
=d=1∑nμ[d]i=1∑nj=1∑np∣i∑q∣i∑[d∣(p,q)]qpj
再化简一下,就是
=
∑
d
=
1
n
μ
[
d
]
∑
d
∣
p
p
∑
d
∣
q
1
q
∑
p
∣
i
∑
q
∣
j
j
= \sum_{d = 1}^n \mu[d] \sum_{d | p} p \sum_{d | q} \frac{1}{q} \sum_{p | i} \sum_{q | j} j
=d=1∑nμ[d]d∣p∑pd∣q∑q1p∣i∑q∣j∑j
也就是
∑
d
=
1
n
μ
[
d
]
∗
d
(
∑
p
=
1
[
n
d
]
p
∗
[
[
n
d
]
p
]
)
(
1
2
∑
q
=
1
[
n
d
]
[
[
n
d
]
p
]
(
[
[
n
d
]
p
]
+
1
)
)
\sum_{d = 1}^n \mu[d] * d (\sum_{p = 1}^{[\frac{n}{d}]} p * [\frac{[\frac{n}{d}]}{p}]) (\frac{1}{2} \sum_{q = 1}^{[\frac{n}{d}]} [\frac{[\frac{n}{d}]}{p}]( [\frac{[\frac{n}{d}]}{p}] + 1))
d=1∑nμ[d]∗d(p=1∑[dn]p∗[p[dn]])(21q=1∑[dn][p[dn]]([p[dn]]+1))
观察一下两个括号里面的东西
会发现实际上就是
∑
i
=
1
n
i
∗
[
n
i
]
\sum_{i = 1}^n i * [\frac{n}{i}]
i=1∑ni∗[in]和
∑
i
=
1
n
[
n
i
]
(
[
n
i
]
+
1
)
2
\sum_{i = 1}^n \frac{[\frac{n}{i}]([\frac{n}{i}] + 1)}{2}
i=1∑n2[in]([in]+1)
前面那个肯定有
∑
i
=
1
n
i
∗
[
n
i
]
=
∑
i
=
1
n
d
(
i
)
\sum_{i = 1}^n i * [\frac{n}{i}] = \sum_{i = 1}^n d(i)
i=1∑ni∗[in]=i=1∑nd(i)
后面那个我们换一下形式,会发现是
∑
i
=
1
n
[
n
i
]
(
[
n
i
]
+
1
)
2
=
∑
i
=
1
n
∑
j
=
1
[
n
i
]
j
\sum_{i = 1}^n \frac{[\frac{n}{i}]([\frac{n}{i}] + 1)}{2} = \sum_{i = 1}^n \sum_{j = 1}^{[\frac{n}{i}]} j
i=1∑n2[in]([in]+1)=i=1∑nj=1∑[in]j
也就是
=
∑
j
=
1
n
j
∑
i
=
1
[
n
j
]
1
=
∑
j
=
1
n
j
[
n
j
]
=\sum_{j = 1}^n j \sum_{i = 1}^{[\frac{n}{j}]} 1 = \sum_{j = 1}^n j [\frac{n}{j}]
=j=1∑nji=1∑[jn]1=j=1∑nj[jn]
所以整个式子就是
∑
d
=
1
n
d
∗
μ
[
d
]
(
∑
i
=
1
[
n
d
]
d
(
i
)
)
2
\sum_{d = 1}^n d * \mu[d] (\sum_{i = 1}^{[\frac{n}{d}]} d(i)) ^ 2
d=1∑nd∗μ[d](i=1∑[dn]d(i))2
那么前面的东西我们卷上
i
d
id
id然后杜教筛,后面的东西我们可以先处理一下前
n
2
/
3
n^{2/3}
n2/3个
d
(
i
)
d(i)
d(i),对于后面的那些我们可以直接利用
∑
i
=
1
n
i
∗
[
n
i
]
\sum_{i = 1}^n i * [\frac{n}{i}]
∑i=1ni∗[in]大力数论分块,这样总复杂度还是
O
(
n
2
/
3
)
O(n^{2/3})
O(n2/3)
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <unordered_map>
using namespace std;
using ll = long long;
int const M = 1000000;
int const N = M + 5;
int const mod = 1e9 + 7;
ll KSM(ll a, ll k) {
ll ret = 1;
for (; k; k >>= 1, a = a * a % mod)
if (k & 1)
ret = ret * a % mod;
return ret;
}
int f[N], c[N], su[N], low[N];
ll g[N];
int pri[N], tot;
bool isp[N];
ll inv2, inv3;
void SAI() {
isp[1] = 1;
low[1] = f[1] = su[1] = 1;
g[1] = 1;
for (int i = 2; i <= M; ++i) {
if (isp[i] == 0) {
pri[++tot] = i;
f[i] = -1;
g[i] = su[i] = i + 1;
low[i] = i;
}
for (int j = 1; j <= tot && i * pri[j] <= M; ++j) {
isp[i * pri[j]] = 1;
if (i % pri[j]) {
f[i * pri[j]] = -f[i];
low[i * pri[j]] = pri[j];
su[i * pri[j]] = pri[j] + 1;
g[i * pri[j]] = g[i] * g[pri[j]];
} else {
f[i * pri[j]] = 0;
low[i * pri[j]] = low[i] * pri[j];
su[i * pri[j]] = su[i] + low[i * pri[j]];
g[i * pri[j]] = g[i] / su[i] * su[i * pri[j]];
break;
}
}
}
for (int i = 1; i <= M; ++i) {
f[i] = (1ll * i * f[i] % mod + f[i - 1]) % mod;
g[i] = (g[i] + g[i - 1]) % mod;
}
}
unordered_map<int, int> mp;
int sum_(int x) {
if (x <= M)
return f[x];
if (mp.count(x) > 0)
return mp[x];
int ret = 1;
for (int l = 2, r; l <= x; l = r + 1) {
r = x / (x / l);
ret = (ret - 1ll * (r - l + 1) * (l + r) % mod * inv2 % mod * sum_(x / l) % mod) % mod;
}
ret = (ret + mod) % mod;
mp[x] = ret;
return ret;
}
int sig_(int x) {
if (x <= M)
return g[x] % mod;
int ret = 0;
for (int l = 1, r; l <= x; l = r + 1) {
r = x / (x / l);
ret += 1ll * (x / l) * (l + r) % mod * (r - l + 1) % mod * inv2 % mod;
if (ret >= mod)
ret -= mod;
}
return ret;
}
int main() {
SAI();
int T = 1;
inv2 = KSM(2, mod - 2);
inv3 = KSM(3, mod - 2);
while (T--) {
int n;
scanf("%d", &n);
int ans = 0;
for (int l = 1, r; l <= n; l = r + 1) {
r = n / (n / l);
int nd = n / l, t = sig_(nd);
ans = (ans + 1ll * t * t % mod * (sum_(r) - sum_(l - 1))) % mod;
}
ans = (ans + mod) % mod;
printf("%d\n", ans);
}
}