Function
Description
σ0(n)
=
∑d|n1
求
Data Constraint
n
<=
Solution
σ0(n)
就是
n
的约数个数。
显然有
设
g(n)
=
σ20(n)
,
f(n)
=
∑d|iμ(d)g(id)
,则有
f=μ∗g
显然
μ
和
g
都是积性函数,所以
题目就是让我们求
∑ni=1f(i)
。
易得
f(pk)
=
2k+1
(其中
p
为质数)
设
由
f
是积性函数可得
所以
Answer
=
∑ni=1σ0(i2)
我们有
σ0(i2)
=
Πwi=1(2ai+1)
将右边的式子拆开,然后考虑每一项的贡献,便可得
经过仔细的思索便可以将上式写成另一种形式
其中 r(d) 表示 d 的不同质因子的个数。
设
考虑
h(x)
的另一个意义即
x
的无平方因子的约数个数,即
再设 t(x)=μ2(x) ,则有 h=t∗1 。
所以
所以
对式子分块求解,预处理出 μ2(i) 和 σ0(i) 前 n23 的前缀和,若超出了这个范围就 O(N−−√) 暴力求解,听说复杂度和杜教筛的复杂度一样,为 O(n23) 。
求 ∑ni=1σ0(i) = ∑ni=1⌊ni⌋ ,分块 O(n−−√) 求解即可。
求
∑ni=1μ2(i)
,考虑从意义出发,这个式子就是让我们求
1
~
O(n−−√) 暴力统计即可。
Code
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define fo(i,j,l) for(int i=j;i<=l;++i)
#define fd(i,j,l) for(int i=j;i>=l;--i)
using namespace std;
typedef long long ll;
const ll K=12e5,N=15e5;
int T,oo;
int mu[N],ss[N],cs[N];
ll qz[N],g[N],q[N],n;
bool bz[N];
inline ll min(ll a,ll b)
{return a<b?a:b;}
inline ll findmu(ll p)
{
if(p<=K)return qz[p];
ll u=(ll)sqrt(p),ans=0;
fo(i,1,u)ans=ans+mu[i]*((p/i)/i);
return ans;
}
inline ll findysh(ll p)
{
if(p<=K)return q[p];
int l=1,r; ll ans=0;
while(l<=p){
r=p/(p/l);
ans=ans+(p/l)*(r-l+1);
l=r+1;
}
return ans;
}
int main()
{
freopen("function.in","r",stdin);
freopen("function.out","w",stdout);
cin>>T;
cs[1]=mu[1]=g[1]=1;
fo(i,2,K){
if(!bz[i])ss[++oo]=i,mu[i]=-1,g[i]=2,cs[i]=2;
fo(j,1,oo){
if(i*ss[j]>K)break;
bz[i*ss[j]]=true;
if(i%ss[j]==0){
mu[i*ss[j]]=0;
cs[i*ss[j]]=cs[i]+1;
g[i*ss[j]]=(g[i]/cs[i])*(cs[i]+1);
break;
}else cs[i*ss[j]]=2,g[i*ss[j]]=g[i]*2,mu[i*ss[j]]=-mu[i];
}
}
fo(i,1,K)qz[i]=qz[i-1]+(mu[i]!=0);
fo(i,1,K)q[i]=q[i-1]+g[i];
fo(tt,1,T){
scanf("%lld",&n);
ll ans=0;
ll l=1,r;
while(l<=n){
r=n/(n/l);
ans=ans+(findmu(r)-findmu(l-1))*findysh(n/l);
l=r+1;
}
printf("%lld\n",ans);
}
}