设
f(x)=∑d|xg(d)
,
G(x)=∑xd=1g(d)
则:
∑ni=1f(i)=∑ni=1∑d|ig(d)=∑nd=1∑ndi=1g(d)=∑nd=1∑ndi=1g(i)=∑nd=1G(nd)
因此
G(n)=∑ni=1f(i)−∑nd=2G(nd)
然后
∑d|xμ(x)=1/0 ∑d|xϕ(x)=n
因此
f(x)
都可以
O(1)
计算。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define M 4000000
#define M1 4000010
bool ip[M1];
ll phi[M1];
int mu[M1],prime[M1/10];
int cnt,T,n;
map<int,ll>a1,a2;
ll f(ll x)
{
if(x<=M)return phi[x];
if(a1.count(x))return a1[x];
ll ret=x*(x+1)/2;
for(ll i=2,last;i<=x;i=last+1)
{
last=x/(x/i);
ret-=f(x/i)*(last-i+1);
}
return a1[x]=ret;
}
ll g(ll x)
{
if(x<=M)return mu[x];
if(a2.count(x))return a2[x];
ll ret=1;
for(ll i=2,last;i<=x;i=last+1)
{
last=x/(x/i);
ret-=g(x/i)*(last-i+1);
}
return a2[x]=ret;
}
void init()
{
mu[1]=1;phi[1]=1;
for(int i=2;i<=M;i++)
{
if(!ip[i])
{
prime[++cnt]=i;
mu[i]=-1;phi[i]=i-1;
}
for(int j=1;j<=cnt&&i*prime[j]<=M;j++)
{
ip[i*prime[j]]=1;
if(i%prime[j]==0)
{
phi[i*prime[j]]=phi[i]*prime[j];
mu[i*prime[j]]=0;
break;
}
phi[i*prime[j]]=phi[i]*(prime[j]-1);
mu[i*prime[j]]=-mu[i];
}
}
for(int i=1;i<=M;i++)
{
phi[i]+=phi[i-1];
mu[i]+=mu[i-1];
}
}
int main()
{
//freopen("tt.in","r",stdin);
init();
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
printf("%lld %lld\n",f(n),g(n));
}
return 0;
}