牛客练习赛76 F phi and phi(莫比乌斯反演)
题解:
前
置
知
识
:
前置知识:
前置知识:
∑
i
=
1
n
∑
j
=
1
n
ϕ
(
i
j
)
=
∑
i
=
1
n
∑
j
=
1
n
ϕ
(
i
)
ϕ
(
j
)
g
c
d
(
i
,
j
)
ϕ
(
g
c
d
(
i
,
j
)
)
\sum_{i=1}^{n}\sum_{j=1}^{n}\phi(ij)=\sum_{i=1}^{n}\sum_{j=1}^{n}\frac{\phi(i)\phi(j)gcd(i,j)}{\phi(gcd(i,j))}
i=1∑nj=1∑nϕ(ij)=i=1∑nj=1∑nϕ(gcd(i,j))ϕ(i)ϕ(j)gcd(i,j)
证
明
:
证明:
证明:
n
=
∏
i
=
1
m
p
i
α
i
n=\prod_{i=1}^{m}p_{i}^{\alpha_{i}}
n=i=1∏mpiαi
ϕ
(
n
)
=
n
∏
i
=
1
m
(
1
−
1
p
i
)
=
n
∏
p
∣
n
(
1
−
1
p
)
\phi(n)=n\prod_{i=1}^{m}(1-\frac{1}{p_{i}})=n\prod_{p|n}(1-\frac{1}{p})
ϕ(n)=ni=1∏m(1−pi1)=np∣n∏(1−p1)
ϕ
(
i
)
=
i
∏
p
1
∣
i
(
1
−
1
p
1
)
,
ϕ
(
j
)
=
j
∏
p
2
∣
j
(
1
−
1
p
2
)
\phi(i)=i\prod_{p_{1}|i}(1-\frac{1}{p_{1}}),\phi(j)=j\prod_{p_{2}|j}(1-\frac{1}{p_{2}})
ϕ(i)=ip1∣i∏(1−p11),ϕ(j)=jp2∣j∏(1−p21)
ϕ
(
i
j
)
=
i
j
∏
p
∣
i
j
(
1
−
1
p
)
=
i
∏
p
1
∣
i
(
1
−
1
p
1
)
×
j
∏
p
2
∣
j
(
1
−
1
p
2
)
∏
p
3
∣
i
,
p
3
∣
j
(
1
−
1
p
3
)
\phi(ij)=ij\prod_{p|ij}(1-\frac{1}{p})=\frac{i\prod_{p_{1}|i}(1-\frac{1}{p_{1}}) \times j\prod_{p_{2}|j}(1-\frac{1}{p_{2}})}{\prod_{p_{3}|i,p_{3}|j}(1-\frac{1}{p_{3}})}
ϕ(ij)=ijp∣ij∏(1−p1)=∏p3∣i,p3∣j(1−p31)i∏p1∣i(1−p11)×j∏p2∣j(1−p21)
=
i
∏
p
1
∣
i
(
1
−
1
p
1
)
×
j
∏
p
2
∣
j
(
1
−
1
p
2
)
g
c
d
(
i
,
j
)
∏
p
3
∣
g
c
d
(
i
,
j
)
(
1
−
1
p
3
)
g
c
d
(
i
,
j
)
=\frac{i\prod_{p_{1}|i}(1-\frac{1}{p_{1}}) \times j\prod_{p_{2}|j}(1-\frac{1}{p_{2}})}{gcd(i,j)\prod_{p_{3}|gcd(i,j)}(1-\frac{1}{p_{3}})}gcd(i,j)
=gcd(i,j)∏p3∣gcd(i,j)(1−p31)i∏p1∣i(1−p11)×j∏p2∣j(1−p21)gcd(i,j)
=
ϕ
(
i
)
ϕ
(
j
)
g
c
d
(
i
,
j
)
ϕ
(
g
c
d
(
i
,
j
)
)
=\frac{\phi(i)\phi(j)gcd(i,j)}{\phi(gcd(i,j))}
=ϕ(gcd(i,j))ϕ(i)ϕ(j)gcd(i,j)
证
完
后
就
可
以
用
上
面
的
公
式
来
推
式
子
了
:
证完后就可以用上面的公式来推式子了:
证完后就可以用上面的公式来推式子了:
∑
i
=
1
n
∑
j
=
1
n
ϕ
(
i
j
)
ϕ
(
g
c
d
(
i
,
j
)
)
=
∑
i
=
1
n
∑
j
=
1
n
ϕ
(
i
)
ϕ
(
j
)
g
c
d
(
i
,
j
)
\sum_{i=1}^{n}\sum_{j=1}^{n}\phi(ij)\phi(gcd(i,j))=\sum_{i=1}^{n}\sum_{j=1}^{n}\phi(i)\phi(j)gcd(i,j)
i=1∑nj=1∑nϕ(ij)ϕ(gcd(i,j))=i=1∑nj=1∑nϕ(i)ϕ(j)gcd(i,j)
枚
举
g
c
d
(
i
,
j
)
:
枚举gcd(i,j):
枚举gcd(i,j):
∑
d
=
1
n
∑
i
=
1
n
∑
j
=
1
n
ϕ
(
i
)
ϕ
(
j
)
d
[
g
c
d
(
i
,
j
)
=
=
d
]
\sum_{d=1}^{n}\sum_{i=1}^{n}\sum_{j=1}^{n}\phi(i)\phi(j)d[gcd(i,j)==d]
d=1∑ni=1∑nj=1∑nϕ(i)ϕ(j)d[gcd(i,j)==d]
=
∑
d
=
1
n
∑
i
=
1
n
/
d
∑
j
=
1
n
/
d
ϕ
(
i
d
)
ϕ
(
j
d
)
d
[
g
c
d
(
i
,
j
)
=
=
1
]
=\sum_{d=1}^{n}\sum_{i=1}^{n/d}\sum_{j=1}^{n/d}\phi(id)\phi(jd)d[gcd(i,j)==1]
=d=1∑ni=1∑n/dj=1∑n/dϕ(id)ϕ(jd)d[gcd(i,j)==1]
=
∑
d
=
1
n
d
∑
i
=
1
n
/
d
∑
j
=
1
n
/
d
ϕ
(
i
d
)
ϕ
(
j
d
)
∑
x
∣
d
μ
(
x
)
=\sum_{d=1}^{n}d\sum_{i=1}^{n/d}\sum_{j=1}^{n/d}\phi(id)\phi(jd)\sum_{x|d}\mu(x)
=d=1∑ndi=1∑n/dj=1∑n/dϕ(id)ϕ(jd)x∣d∑μ(x)
=
∑
d
=
1
n
d
∑
x
=
1
n
/
d
μ
(
x
)
∑
i
=
1
n
/
d
x
∑
j
=
1
n
/
d
x
ϕ
(
i
d
x
)
ϕ
(
j
d
x
)
=\sum_{d=1}^{n}d\sum_{x=1}^{n/d}\mu(x)\sum_{i=1}^{n/dx}\sum_{j=1}^{n/dx}\phi(idx)\phi(jdx)
=d=1∑ndx=1∑n/dμ(x)i=1∑n/dxj=1∑n/dxϕ(idx)ϕ(jdx)
令
T
=
d
x
:
令T=dx:
令T=dx:
∑
T
=
1
n
∑
d
∣
T
d
μ
(
T
d
)
(
∑
i
=
1
n
/
T
ϕ
(
i
T
)
)
2
\sum_{T=1}^{n}\sum_{d|T}d\mu(\frac{T}{d})(\sum_{i=1}^{n/T}\phi(iT))^{2}
T=1∑nd∣T∑dμ(dT)(i=1∑n/Tϕ(iT))2
前
面
一
部
分
用
狄
利
克
雷
卷
积
可
以
求
出
来
:
μ
∗
i
d
=
ϕ
,
于
是
就
可
以
进
一
步
化
简
了
:
前面一部分用狄利克雷卷积可以求出来:\mu*id=\phi,于是就可以进一步化简了:
前面一部分用狄利克雷卷积可以求出来:μ∗id=ϕ,于是就可以进一步化简了:
∑
T
=
1
n
ϕ
(
T
)
(
∑
i
=
1
n
/
T
ϕ
(
i
T
)
)
2
\sum_{T=1}^{n}\phi(T)(\sum_{i=1}^{n/T}\phi(iT))^{2}
T=1∑nϕ(T)(i=1∑n/Tϕ(iT))2
令
f
(
d
,
n
)
=
∑
i
=
1
n
/
d
ϕ
(
i
d
)
,
我
们
发
现
对
于
n
∈
[
i
×
d
,
(
i
+
1
)
×
d
)
,
ϕ
(
d
)
×
f
(
d
,
n
)
2
的
贡
献
是
相
同
的
,
即
这
一
区
间
都
要
加
上
这
一
贡
献
,
所
以
就
可
以
用
差
分
+
前
缀
和
来
求
了
,
时
间
复
杂
度
大
概
为
O
(
n
l
o
g
n
)
.
令f(d,n)=\sum_{i=1}^{n/d}\phi(id),我们发现对于n\in[i\times d,(i+1)\times d),\phi(d)\times f(d,n)^{2}的贡献是相同的,即这一区间都要加上这一贡献,所以就可以用差分+前缀和来求了,时间复杂度大概为O(nlogn).
令f(d,n)=∑i=1n/dϕ(id),我们发现对于n∈[i×d,(i+1)×d),ϕ(d)×f(d,n)2的贡献是相同的,即这一区间都要加上这一贡献,所以就可以用差分+前缀和来求了,时间复杂度大概为O(nlogn).
代码:
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e6 + 5, mod = 1e9 + 7;
int n, phi[N], p[N], cnt, ans[N];
bool vis[N];
void get() {
phi[1] = 1;
for(int i = 2; i <= n; i++) {
if(!vis[i]) {
p[cnt++] = i;
phi[i] = i - 1;
}
for(int j = 0; p[j] <= n / i; j++) {
vis[i * p[j]] = 1;
if(i % p[j] == 0) {
phi[i * p[j]] = phi[i] * p[j];
break;
}
phi[i * p[j]] = phi[i] * (p[j] - 1);
}
}
}
int main() {
scanf("%d", &n); get();
for(int i = 1; i <= n; i++) {
ll sum = 0;
for(int j = 1; j * i <= n; j++) {
int x = i * j, y = i * (j + 1);
sum = (sum + phi[x]) % mod;
ll tmp = sum * sum % mod * phi[i] % mod;
ans[x] = (ans[x] + tmp) % mod;
if(y <= n) ans[y] = (ans[y] - tmp + mod) % mod;
}
}
for(int i = 1; i <= n; i++) {
ans[i] = (ans[i] + ans[i - 1]) % mod;
printf("%d\n", ans[i]);
}
return 0;
}