题目
子问题:
∑ i = 1 n φ ( i ) ~~~~\sum_{i=1}^{n}\varphi(i) ∑i=1nφ(i)
因为
∑ i ∣ n φ ( i ) = n ~~~~\sum_{i|n}\varphi(i)=n ∑i∣nφ(i)=n
所以
φ ( n ) = n − ∑ i ∣ n , i < n φ ( i ) ~~~~\varphi(n)=n-\sum_{i|n,i<n}\varphi(i) φ(n)=n−∑i∣n,i<nφ(i)
辣么
∑ i = 1 n φ ( i ) ~~~~\sum_{i=1}^{n}\varphi(i) ∑i=1nφ(i)
= ∑ i = 1 n ( i − ∑ d ∣ i , d < i φ ( d ) ) =\sum_{i=1}^{n}(i-\sum_{d|i,d<i}\varphi(d)) =∑i=1n(i−∑d∣i,d<iφ(d))
= n ( n + 1 ) 2 − ∑ i = 2 n ∑ d ∣ i , d < i φ ( d ) =\frac{n(n+1)}{2}-\sum_{i=2}^{n}\sum_{d|i,d<i}\varphi(d) =2n(n+1)−∑i=2n∑d∣i,d<iφ(d)
= n ( n + 1 ) 2 − ∑ i = 2 n ∑ d = 1 ⌊ n i ⌋ φ ( d ) =\frac{n(n+1)}{2}-\sum_{i=2}^{n}\sum_{d=1}^{\lfloor\frac{n}{i}\rfloor}\varphi(d) =2n(n+1)−∑i=2n∑d=1⌊in⌋φ(d)
同理
子问题:
∑ i = 1 n μ ( i ) ~~~~\sum_{i=1}^{n}\mu(i) ∑i=1nμ(i)
因为
∑ i ∣ n μ ( i ) = [ i = = 1 ] ~~~~\sum_{i|n}\mu(i)=[i==1] ∑i∣nμ(i)=[i==1]
所以
φ ( n ) = [ n = = 1 ] − ∑ i ∣ n , i < n φ ( i ) ~~~~\varphi(n)=[n==1]-\sum_{i|n,i<n}\varphi(i) φ(n)=[n==1]−∑i∣n,i<nφ(i)
辣么
∑ i = 1 n μ ( i ) ~~~~\sum_{i=1}^{n}\mu(i) ∑i=1nμ(i)
= ∑ i = 1 n ( [ i = = 1 ] − ∑ d ∣ i , d < i μ ( d ) ) =\sum_{i=1}^{n}([i==1]-\sum_{d|i,d<i}\mu(d)) =∑i=1n([i==1]−∑d∣i,d<iμ(d))
= 1 − ∑ i = 2 n ∑ d ∣ i , d < i μ ( d ) =1-\sum_{i=2}^{n}\sum_{d|i,d<i}\mu(d) =1−∑i=2n∑d∣i,d<iμ(d)
= 1 − ∑ i = 2 n ∑ d = 1 ⌊ n i ⌋ μ ( d ) =1-\sum_{i=2}^{n}\sum_{d=1}^{\lfloor\frac{n}{i}\rfloor}\mu(d) =1−∑i=2n∑d=1⌊in⌋μ(d)
两个子问题都可以用杜教筛 O ( n 2 3 ) O(n^{\frac{2}{3}}) O(n32)下求解
代码:
#include<cstdio>
#include<cmath>
#include<cstring>
#include<map>
#include<vector>
#include<iostream>
#include<algorithm>
#define maxn 5000000
using namespace std;
inline int getint()
{
int num=0,flag=1;char c;
while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
return num*flag;
}
map<long long,long long>Mu,Phi;
bool not_prime[maxn+5];
long long phi[maxn+5],mu[maxn+5],prime[maxn+5],cnt;
long long n;
inline void init()
{
mu[1]=phi[1]=1;
for(int i=2;i<=maxn;i++)
{
if(!not_prime[i])prime[++cnt]=i,mu[i]=-1,phi[i]=i-1;
for(int j=1;j<=cnt&&i*prime[j]<=maxn;j++)
{
not_prime[i*prime[j]]=1;
if(i%prime[j])mu[i*prime[j]]=-mu[i],phi[i*prime[j]]=phi[i]*phi[prime[j]];
else{phi[i*prime[j]]=phi[i]*prime[j];break;}
}
}
for(int i=1;i<=maxn;i++)phi[i]+=phi[i-1],mu[i]+=mu[i-1];
}
inline long long solvephi(long long x)
{
if(x<=maxn)return phi[x];
if(Phi.count(x))return Phi[x];
long long Sum=1ll*x*(1ll*x+1)/2;
for(long long i=2,j;i<=x;i=j+1)
j=min(x/(x/i),x),Sum-=1ll*(j-i+1)*solvephi(x/i);
return Phi[x]=Sum;
}
inline long long solvemu(long long x)
{
if(x<=maxn)return mu[x];
if(Mu.count(x))return Mu[x];
long long Sum=1;
for(long long i=2,j;i<=x;i=j+1)
j=min(x/(x/i),x),Sum-=1ll*(j-i+1)*solvemu(x/i);
return Mu[x]=Sum;
}
int main()
{
init();
int T=getint();
while(T--)
{
n=getint();
printf("%lld %lld\n",solvephi(n),solvemu(n));
}
}