杜教筛
题解:
还是好神奇啊。。。(依旧很套路啊)
https://blog.csdn.net/qq_30974369/article/details/79087445
杜教筛的复杂度是$n^{\frac{2}{3}}$的
1.杜教筛求mu(i)前缀和
这个首先要知道
$\sum(mu[i]) \ i|n = (n==1)$
2.杜教筛求欧拉函数前缀和
$\sum(phi[i]) \ i|n =i$ 这个推导也很套路啊。。
https://blog.csdn.net/zzkksunboy/article/details/78902549
bzoj 3944
这测试数据好像有点问题 第13组开始就不是这题的?
为了卡一波常数可以先预处理出1e7之内的
毕竟数组访问比map快多了(当然还可以hash优化)
#include <bits/stdc++.h> using namespace std; #define rint register int #define IL inline #define rep(i,h,t) for (int i=h;i<=t;i++) #define dep(i,t,h) for (int i=t;i>=h;i--) #define ll long long const int N=1e7+10; const int M=1e7+1e5; ll phi[M],mu[N]; int p[N],cnt; bool t[M]; map<ll,ll> M1,P1; ll Phi(ll x) { if (x<=N) return(phi[x]); if (P1[x]) return(P1[x]); ll i=2; ll ans=x*(x+1)/2; while (i<=x) { ll j=x/(x/i); ans-=(j-i+1)*Phi(x/i); i=j+1; } P1[x]=ans; return ans; } ll Mu(ll x) { if (x<=N) return(mu[x]); if (M1[x]) return(M1[x]); ll i=2; ll ans=1; while(i<=x) { ll j=x/(x/i); ans-=(j-i+1)*Mu(x/i); i=j+1; } M1[x]=ans; return ans; } int main() { freopen("1.in","r",stdin); freopen("1.out","w",stdout); ios::sync_with_stdio(false); mu[1]=phi[1]=1; t[1]=1; rep(i,2,N) { if (!t[i]) p[++cnt]=i,mu[i]=-1,phi[i]=i-1; for (int j=1;j<=cnt&&i*p[j]<=N;j++) { t[i*p[j]]=1; if (i%p[j]==0) { phi[i*p[j]]=phi[i]*p[j]; mu[i*p[j]]=0; break; } else { mu[i*p[j]]=-mu[i]; phi[i*p[j]]=phi[i]*phi[p[j]]; } } } rep(i,1,N) phi[i]+=phi[i-1],mu[i]+=mu[i-1]; int T; cin>>T; while (T--) { ll n; cin>>n; cout<<Phi(n)<<" "<<Mu(n)<<endl; } return 0; }