Comet OJ - Contest #8 E神奇函数(莫比乌斯函数容斥)
题目大意
定义
d
(
x
)
d(x)
d(x)的值为x的最小素因子,定义
f
(
x
)
=
{
1
x
=
1
d
(
x
)
f
(
x
d
2
(
x
)
)
x
>
1
,
d
2
(
x
)
∣
x
d
(
x
)
f
(
x
d
(
x
)
)
o
t
h
e
r
f(x)= \begin{cases} 1&x=1\\ d(x)f(\frac{x}{d^2(x)}) &x>1,d^2(x)|x\\ d(x)f(\frac{x}{d(x)})&other \end{cases}
f(x)=⎩⎪⎨⎪⎧1d(x)f(d2(x)x)d(x)f(d(x)x)x=1x>1,d2(x)∣xother
求f函数前缀和
https://cometoj.com/contest/58/problem/E?problem_id=2759
解题思路
f函数的值实际上就是x的最大平方因子开根号为此我们枚举原式
∑
i
=
1
n
i
⋅
g
(
⌊
n
i
2
⌋
)
\sum_{i=1}^{\sqrt{n}}i\cdot g(\left\lfloor\frac{n}{i^2}\right\rfloor)
i=1∑ni⋅g(⌊i2n⌋)
其中
g
(
x
)
g(x)
g(x)的定义是小于等于x的,无完全平方因子的数的数量。这就是一个非常经典的容斥原理的题目了。即枚举无素数平方因子,至少有一个素数平方因子,至少有两个素数平方因子,…对此进行容斥,发现容斥的系数恰好枚举的数的莫比乌斯函数的值,则有
g
(
x
)
=
∑
i
=
1
x
μ
(
i
)
⋅
⌊
n
i
2
⌋
g(x)=\sum_{i=1}^{\sqrt x}\mu(i)\cdot\left\lfloor\frac{n}{i^2}\right\rfloor
g(x)=i=1∑xμ(i)⋅⌊i2n⌋
故原式等于
∑
i
=
1
n
i
⋅
∑
j
=
1
⌊
n
i
2
⌋
μ
(
j
)
⌊
n
i
2
j
2
⌋
\sum_{i=1}^{\sqrt n}i\cdot\sum_{j=1}^{\sqrt{\left\lfloor\frac{n}{i^2}\right\rfloor}}\mu(j)\left\lfloor\frac{n}{i^2j^2}\right\rfloor
i=1∑ni⋅j=1∑⌊i2n⌋μ(j)⌊i2j2n⌋
设
k
=
i
⋅
j
k=i\cdot j
k=i⋅j,将原式改变为枚举k,则有
∑
k
=
1
n
⌊
n
k
2
⌋
∑
i
∣
k
i
⋅
μ
(
k
i
)
\sum_{k=1}^{\sqrt n}\left\lfloor\frac{n}{k^2}\right\rfloor\sum_{i|k}i\cdot\mu(\frac{k}{i})
k=1∑n⌊k2n⌋i∣k∑i⋅μ(ik)
可以发现后面那个式子就是单位函数卷积莫比乌斯函数,根据公式已知其值为欧拉函数,故原式可以写作
∑
k
=
1
n
⌊
n
k
2
⌋
φ
(
k
)
\sum_{k=1}^{\sqrt n}\left\lfloor\frac{n}{k^2}\right\rfloor\varphi(k)
k=1∑n⌊k2n⌋φ(k)
AC代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
typedef long long LL;
LL n;
const int size=1e7+5;
bool prime[size];int p[size];
int phi[size];
int tot=0;
void init()
{
phi[1]=1;
for(int i=1;i<size;i++) prime[i]=true;
for(int i=2;i<size;i++)
{
if(prime[i])
{
p[++tot]=i;
phi[i]=i-1;
}
for(int j=1;j<=tot&&p[j]*i<size;j++)
{
prime[i*p[j]]=false;
if(i%p[j]==0)
{
phi[i*p[j]]=phi[i]*p[j];
break;
}
else phi[i*p[j]]=phi[i]*phi[p[j]];
}
}
}
int32_t main()
{
int t;
//freopen("a.in","r",stdin);
init();
scanf("%lld",&t);
while(t--)
{
scanf("%lld",&n);
int s=sqrt(n);
LL ans=0;
for(int i=1;i<=s;i++)
{
ans+=n/(i*i)*phi[i];
}
printf("%lld\n",ans);
}
}