长链剖分,每条链用类似分块的方式维护深度%x=y的个数,可以自底向上合并信息。
#include<bits/stdc++.h> typedef long long i64; const int N=2e5+7; char rb[N*12],*rp=rb; int _(){ int x=0; while(*rp<48)++rp; while(*rp>47)x=x*10+*rp++-48; return x; } std::vector<int>e[N]; int n,md[N],top[N],dep[N],dc[N]; i64 ans[N]; inline void maxs(int&a,int b){if(a<b)a=b;} inline bool cmp_md(int a,int b){return md[a]<md[b];} template<class T> inline T*$(int L,int R){ static T mem[N*5],*mp=mem; T*r=mp-L; mp+=R-L+1; return r; } struct dat{ int mx,B,*d1,**d2,*d3; void ins(int x,int y){ for(int i=1;i<=B;++i)d2[i][x%i]+=y; d1[x]+=y; } int que(int x,int y){ if(x<=B)return d2[x][y]; int s=0; if(!y)y=x; for(int i=y;i<=mx;i+=x)s+=d1[i]; return s; } void init(int n){ B=sqrt(mx=n); d1=$<int>(1,mx); d2=$<int*>(1,B); for(int i=1;i<=B;++i)d2[i]=$<int>(0,i-1); } void cal(){ d3=$<int>(1,mx); for(int i=1;i<=mx;++i){ for(int j=i;j<=mx;j+=i)d3[i]+=d1[j]; } } void mg1(dat&w){ for(int i=1;i<=w.mx;++i){ d1[i]+=w.d1[i]; ans[i]+=i64(d3[i])*w.d3[i]; d3[i]+=w.d3[i]; } } void mg2(dat&w,int d){ for(int i=1;i<=w.mx;++i){ ans[i]+=i64(w.d3[i])*que(i,d%i); } for(int i=1;i<=w.mx;++i){ ins(d+i,w.d1[i]); } } }ds[N]; void f1(int w){ ++dc[dep[w]]; for(int i=0;i<e[w].size();++i){ int u=e[w][i]; dep[u]=dep[w]+1; f1(u); maxs(md[w],md[u]+1); } std::sort(e[w].begin(),e[w].end(),cmp_md); } void f2(int w,int tp){ top[w]=tp; if(e[w].empty())ds[tp].init(dep[w]-dep[tp]+1); else{ int sz=e[w].size(); f2(e[w][sz-1],tp); if(sz>1){ int u; for(int i=0;i<sz-1;++i){ u=e[w][i]; f2(u,u); ds[u].cal(); if(i)ds[u].mg1(ds[e[w][i-1]]); } u=e[w][sz-2]; ds[tp].mg2(ds[u],dep[u]-dep[tp]); } } ds[tp].ins(dep[w]-dep[tp]+1,1); } int ps[N/5],pp=0,mu[N]; bool np[N]; int main(){ fread(rb,1,sizeof(rb),stdin); n=_(); mu[1]=1; for(int i=2;i<=n;++i){ if(!np[i])ps[pp++]=i,mu[i]=-1; for(int j=0,k;j<pp&&(k=i*ps[j])<=n;++j){ np[k]=1; if(i%ps[j])mu[k]=-mu[i]; else break; } } for(int i=2;i<=n;++i)e[_()].push_back(i); f1(1); f2(1,1); for(int i=n;i;--i)dc[i]+=dc[i+1]; for(int i=1;i<n;++i){ i64 s=0; for(int j=i,k=1;j<=n;j+=i,++k)s+=ans[j]*mu[k]; printf("%lld\n",s+dc[i]); } return 0; }