小清新数论
心情:蒻蒻的第一道莫比乌斯反演!!看了好几个小时QAQ,终于看懂些了!开心!^_^
题解:
(1)
∑
i
=
1
n
∑
j
=
1
n
μ
(
g
c
d
(
i
,
j
)
)
\sum_{i = 1}^n\sum_{j = 1}^n \mu(gcd(i,j)) \tag 1
i=1∑nj=1∑nμ(gcd(i,j))(1)
(2)
∑
d
=
1
n
∑
i
=
1
n
∑
j
=
1
n
μ
(
d
)
[
g
c
d
(
i
,
j
)
=
=
d
]
\sum_{d = 1}^n\sum_{i = 1}^n\sum_{j = 1}^n\mu(d)[gcd(i,j) = =d]\tag 2
d=1∑ni=1∑nj=1∑nμ(d)[gcd(i,j)==d](2)
(3)
∑
d
=
1
n
μ
(
d
)
∑
i
=
1
n
∑
j
=
1
n
[
g
c
d
(
i
,
j
)
=
=
d
]
\sum_{d = 1}^n\mu(d)\sum_{i = 1}^n\sum_{j = 1}^n[gcd(i,j) = =d]\tag 3
d=1∑nμ(d)i=1∑nj=1∑n[gcd(i,j)==d](3)
设
g
(
d
)
=
∑
i
=
1
n
∑
j
=
1
n
[
g
c
d
(
i
,
j
)
=
=
d
]
g(d) =\sum_{i = 1}^n\sum_{j = 1}^n[gcd(i,j) = =d]
g(d)=∑i=1n∑j=1n[gcd(i,j)==d],
f
(
d
)
f(d)
f(d)为满足
d
∣
g
c
d
(
i
,
j
)
d|gcd(i,j)
d∣gcd(i,j)的对数,那么我们就有
(4)
f
(
d
)
=
∑
i
=
1
⌊
n
d
⌋
g
(
d
⋅
i
)
f(d) = \sum_{i = 1}^{\lfloor \frac{n}{d}\rfloor}g(d\cdot i)\tag 4
f(d)=i=1∑⌊dn⌋g(d⋅i)(4)
如果我们要求有多少
g
c
d
(
i
,
j
)
gcd(i,j)
gcd(i,j)可以整除
d
d
d,那么必定
i
=
d
⋅
x
,
j
=
d
⋅
x
i = d \cdot x, j = d \cdot x
i=d⋅x,j=d⋅x,因此
(5)
f
(
d
)
=
⌊
n
d
⌋
⋅
⌊
n
d
⌋
f(d) = \lfloor \frac{n}{d}\rfloor \cdot \lfloor \frac{n}{d} \rfloor\tag 5
f(d)=⌊dn⌋⋅⌊dn⌋(5)
此时我们对
(
4
)
(4)
(4)进行莫比乌斯反演
(6)
g
(
d
)
=
∑
i
=
1
⌊
n
d
⌋
f
(
d
⋅
i
)
μ
(
i
)
g(d) = \sum_{i = 1}^{\lfloor \frac{n}{d}\rfloor}f(d \cdot i)\mu(i)\tag 6
g(d)=i=1∑⌊dn⌋f(d⋅i)μ(i)(6)
(7)
g
(
d
)
=
∑
i
=
1
⌊
n
d
⌋
⌊
n
d
⋅
i
⌋
2
μ
(
i
)
g(d)= \sum_{i = 1}^{\lfloor \frac{n}{d}\rfloor} {\lfloor \frac{n}{d\cdot i}\rfloor }^2\mu(i)\tag 7
g(d)=i=1∑⌊dn⌋⌊d⋅in⌋2μ(i)(7)
所以最后的
(8)
a
n
s
=
∑
d
=
1
n
μ
(
d
)
g
(
d
)
ans =\sum_{d = 1}^{n}\mu(d)g(d)\tag 8
ans=d=1∑nμ(d)g(d)(8)
最后再在求
g
(
d
)
g(d)
g(d)和
μ
(
d
)
\mu(d)
μ(d)的时候用除法分块就好了,总的复杂度为
O
(
N
)
O(N)
O(N)。
代码
#include<bits/stdc++.h>
typedef long long LL;
using namespace std;
const int N = 1E7+10, mod = 998244353;
int prime[N], mu[N], cnt, n;
bool vis[N];
void get_M()
{
mu[1] = 1;
for(int i = 2; i < N; ++i) {
if(vis[i] == 0) {
prime[cnt++] = i;
mu[i] = -1;
}
for(int j = 0; j < cnt && prime[j] * i < N; ++j) {
vis[i * prime[j]] = 1;
if(i % prime[j] == 0) break;
mu[prime[j] * i] = -mu[i];
}
}
for(int i = 1; i < N; ++i) {
mu[i] = mu[i - 1] + mu[i];
}
}
LL g(int d)
{
LL ans = 0;
for(int i = 1, last = 1; i <= n / d; i = last + 1) {
last = n / (n / i);
ans = (ans + (mu[last] - mu[i - 1] + mod) * (1LL * (n / d / i) * (n / d / i) % mod) ) % mod;
}
return ans;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("input.in","r",stdin);
#endif
get_M();
LL ans = 0;
cin >> n;
for(int i = 1, last = 1; i <= n; i = last + 1) {
last = n / (n / i);
ans = (ans + g(i) * (mu[last] - mu[i - 1] + mod)) % mod;
}
cout << ans << endl;
return 0;
}