杜教筛模板题:
对于
∑
i
=
1
n
μ
i
\sum_{i=1}^n{\mu_i}
∑i=1nμi,有
μ
∗
I
=
ϵ
\mu*I=\epsilon
μ∗I=ϵ,由
μ
\mu
μ的性质或者容斥原理得到
对于
∑
i
=
1
n
ϕ
i
\sum_{i=1}^n{\phi_i}
∑i=1nϕi,有
ϕ
∗
I
=
I
d
\phi*I=Id
ϕ∗I=Id,将
ϕ
i
\phi_i
ϕi看做是有多少个分母为
i
i
i的最简真分数,则对于
1
−
n
1-n
1−n的所有数,都只对一个
d
∣
n
d|n
d∣n的
ϕ
d
\phi_d
ϕd有1的贡献,则通过分母类统计得到
ϕ
∗
I
=
I
d
\phi*I=Id
ϕ∗I=Id
Code:
#include<bits/stdc++.h>
#include<tr1/unordered_map>
#define ll long long
using namespace std;
inline int read(){
int res=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
return res*f;
}
const int P=8e6+7,N=P-7,INF=0x7fffffff;
int pri[P],cnt,mu[P];
bool pt[P];
ll phi[P];
inline void init(){
phi[1]=mu[1]=1;
for(int i=2;i<=N;i++){
if(!pt[i]) pri[++cnt]=i,phi[i]=i-1,mu[i]=-1;
for(int j=1;j<=cnt && i*pri[j]<=N;j++){
pt[i*pri[j]]=1;
if(i%pri[j]==0){
phi[i*pri[j]]=phi[i]*pri[j];
mu[i*pri[j]]=0;
break;
}
phi[i*pri[j]]=phi[i]*(pri[j]-1);
mu[i*pri[j]]=-mu[i];
}
mu[i]+=mu[i-1];
phi[i]+=phi[i-1];
}
}
namespace solve_mu{
tr1::unordered_map<int,int>sum;
int get(int n){
if(n<=N) return mu[n];
if(sum[n]) return sum[n];
int ans=1;
for(int i=2,j;j<INF && i<=n;i=j+1){
j=n/(n/i);
ans-=(j-i+1)*get(n/i);
}
return sum[n]=ans;
}
}
namespace solve_phi{
tr1::unordered_map<int,ll>sum;
ll get(int n){
if(n<=N) return phi[n];
if(sum[n]) return sum[n];
ll ans=n*((ll)n+1)/2;
for(int i=2,j;j<INF && i<=n;i=j+1){
j=n/(n/i);
ans-=(j-i+1)*get(n/i);
}
return sum[n]=ans;
}
}
int main(){
init();int t=read();
while(t--){
int n=read();
cout<<solve_phi::get(n)<<" "<<solve_mu::get(n)<<"\n";
}
return 0;
}