题意:
给你
n
n
n,求
∑
i
=
1
n
μ
(
i
2
)
\sum_{i=1}^n\mu(i^2)
∑i=1nμ(i2)和
∑
i
=
1
n
ϕ
(
i
2
)
\sum_{i=1}^n\phi(i^2)
∑i=1nϕ(i2),
n
<
=
1
e
9
n<=1e9
n<=1e9
题解:
对于
∑
i
=
1
n
μ
(
i
2
)
\sum_{i=1}^n\mu(i^2)
∑i=1nμ(i2),这个东西的值其实就是1。。。原因是除了
μ
(
1
)
=
1
\mu(1)=1
μ(1)=1以外,其他都因为是某个数的平方,所以都含平方因子,于是值都是0。
重点就是求 ∑ i = 1 n ϕ ( i 2 ) \sum_{i=1}^n\phi(i^2) ∑i=1nϕ(i2)。我们知道, ϕ ( n ) = n ∗ ∏ i = 1 k p i − 1 p i \phi(n)=n*\prod_{i=1}^k\frac{p_i-1}{p_i} ϕ(n)=n∗∏i=1kpipi−1,所以 ϕ ( n 2 ) = n 2 ∗ ∏ i = 1 k p i − 1 p i = n ∗ ϕ ( n ) \phi(n^2)=n^2*\prod_{i=1}^k\frac{p_i-1}{p_i}=n*\phi(n) ϕ(n2)=n2∗∏i=1kpipi−1=n∗ϕ(n),也就可以转化成求 ∑ i = 1 n i d ( i ) ∗ ϕ ( i ) \sum_{i=1}^nid(i)*\phi(i) ∑i=1nid(i)∗ϕ(i)。
然后我们考虑用杜教筛来筛这个东西。我们考虑构造
g
g
g,我们选择
i
d
id
id作为
g
g
g函数,这样我们有
h
(
i
)
=
f
(
i
)
∗
g
(
i
)
h(i)=f(i)*g(i)
h(i)=f(i)∗g(i)
h
(
i
)
=
∑
d
∣
i
(
i
d
(
d
)
∗
ϕ
(
d
)
)
∗
i
d
(
i
d
)
=
i
∑
d
∣
i
ϕ
(
d
)
=
i
2
h(i)=\sum_{d|i}(id(d)*\phi(d))*id(\frac{i}{d})=i\sum_{d|i}\phi(d)=i^2
h(i)=d∣i∑(id(d)∗ϕ(d))∗id(di)=id∣i∑ϕ(d)=i2
带入杜教筛的式子可得:
S
(
n
)
=
∑
i
=
1
n
i
2
−
∑
i
=
2
n
i
d
(
i
)
S
(
⌊
n
i
⌋
)
S(n)=\sum_{i=1}^ni^2-\sum_{i=2}^nid(i)S(\lfloor\frac{n}{i}\rfloor)
S(n)=i=1∑ni2−i=2∑nid(i)S(⌊in⌋),前面的可以用平方求和公式,后面的可以用等差数列+整除分块和递归下去做就好了。
代码:
#include <bits/stdc++.h>
using namespace std;
int phi[1000010],vis[1000010],p[1000010],cnt;
map<long long,long long> mp;
long long ni,ans,ni2,n,sum[1000010];
const long long mod=1e9+7;
inline long long ksm(long long x,long y)
{
long long res=1;
while(y)
{
if(y&1)
res=res*x%mod;
x=x*x%mod;
y>>=1;
}
return res;
}
inline long long calc(long long x)
{
if(x<=1000000)
return sum[x];
if(mp[x])
return mp[x];
long long r,res=0;
res=x*(x+1)%mod*(2*x+1)%mod*ni%mod;
for(long long l=2;l<=x;l=r+1)
{
r=x/(x/l);
res=(res-1ll*(r-l+1)*(r+l)%mod*ni2%mod*calc(x/l)%mod)%mod;
res=(res+mod)%mod;
}
mp[x]=res;
return res;
}
int main()
{
scanf("%lld",&n);
printf("1\n");
phi[1]=1;
sum[1]=1;
for(int i=2;i<=1000000;++i)
{
if(!vis[i])
{
p[++cnt]=i;
phi[i]=i-1;
}
for(int j=1;j<=cnt&&p[j]*i<=1000000;++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);
}
sum[i]=(sum[i-1]+(long long)i*phi[i])%mod;
}
ni=ksm(6,mod-2);
ni2=ksm(2,mod-2);
printf("%lld\n",calc(n));
return 0;
}