求
∑k=1nfk
令
gn=∑d|nfd
设
Fn=∑i=1nfiGn=∑i=1ngn
Gn=∑k=1n∑d|kfd=∑d=1n∑d|kfd=∑d=1n⌊nd⌋fd=∑d=1nF⌊nd⌋=Fn+∑d=2nF⌊nd⌋
如果能快速求出Gn就能过记忆化搜索得到fn
莫比乌斯函数中
e(n)=n==1?1:0所以G(n)=1
欧拉函数中
id(n)=∑i|nφ(i) 所以 G(n)=∑i=1n∑d|iφ(d)=∑i=1nid(i)=n∗(n+1)2
#include<cstdio>
#include<cstring>
#include<iostream>
#define LL long long
#define maxn 6500010
using namespace std;
int pri[maxn],cnt,T,vu[100011],vp[100011],tim;
LL mu[maxn],phi[maxn],su[100011],sp[100011],n;
void pre(){
mu[1]=phi[1]=1;
for(int i=2;i<maxn;i++){
if(!phi[i])phi[i]=i-1,mu[i]=-1,pri[++cnt]=i;
for(int j=1;j<=cnt&&pri[j]*i<maxn;j++){
mu[i*pri[j]]=-mu[i];
phi[i*pri[j]]=phi[i]*phi[pri[j]];
if(i%pri[j]==0){
mu[i*pri[j]]=0;phi[i*pri[j]]=phi[i]*pri[j];
break;
}
}
}
for(int i=2;i<maxn;i++)phi[i]+=phi[i-1],mu[i]+=mu[i-1];
}
LL solve1(LL x){
if(x<maxn)return phi[x];
if(vp[n/x]==tim)return sp[n/x];
LL ans=x*(x+1)/2ll;
for(LL j,i=2;i<=x;i=j+1){
j=x/(x/i);ans-=(j-i+1)*solve1(x/i);
}vp[n/x]=tim;
return sp[n/x]=ans;
}
LL solve2(LL x){
if(x<maxn)return mu[x];
if(vu[n/x]==tim)return su[n/x];
LL ans=1ll;
for(LL j,i=2;i<=x;i=j+1){
j=x/(x/i);ans-=(j-i+1)*solve2(x/i);
}vu[n/x]=tim;
return su[n/x]=ans;
}
int main(){
pre();
scanf("%d",&T);
while(T--){
scanf("%lld",&n);
tim++;
printf("%lld %lld\n",solve1(n),solve2(n));
}
return 0;
}