#include <iostream>#include<cstdio>#include<algorithm>#include<cmath>#include<cstring>using namespacestd;intRead () {intx=0, f=1;CharCh=GetChar (); while(ch<'0'|| Ch>'9') {if(ch=='-') f=-1; Ch=GetChar ();} while(ch>='0'&& ch<='9') {x=x*Ten+ch-'0'; Ch=GetChar ();} returnx*F;}#defineMAXN 200010intN,m,fa[maxn],root,tmp,block,siz;structedgenode{intNext,to;} edge[maxn<<1];inthead[maxn],cnt;voidAddintUintV) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v;}voidInsertintUintV) {fa[v]=u; Add (u,v); add (v,u);}intSIZE[MAXN],MAXX[MAXN];BOOLVISIT[MAXN];voidGetroot (intNowintFA) {Size[now]=1; maxx[now]=0; for(intI=head[now]; I I=edge[i].next)if(EDGE[I].TO!=FA &&!)Visit[edge[i].to]) {getroot (Edge[i].to,now); Size[now]+=Size[edge[i].to]; Maxx[now]=Max (maxx[now],size[edge[i].to]); } Maxx[now]=max (maxx[now],siz-Size[now]); if(Maxx[now]<maxx[root]) root=Now ;}intNUM[MAXN],DEEP[MAXN];voidDfsdeep (intNowintFA) {Num[deep[now]]++; for(intI=head[now]; I I=edge[i].next)if(EDGE[I].TO!=FA &&!)Visit[edge[i].to]) {Deep[edge[i].to]=deep[now]+1; Dfsdeep (Edge[i].to,now); } if(deep[now]>tmp) tmp=Deep[now];}Long Longs[maxn],ans[maxn],ans[maxn],tim[maxn],num[maxn],tim[maxn],f[510][510];voidGetans (intNow ) {Visit[now]=1; intMaxd=0, maxd=0; for(intI=head[now]; I I=edge[i].next)if(!visit[edge[i].to] && edge[i].to!=Fa[now]) {Deep[edge[i].to]=1; TMP=0; Dfsdeep (Edge[i].to,now); if(Tmp>maxd) maxd=tmp; for(intj=1; j<=tmp; J + +) for(intK=j; k<=tmp; k+=j) Tim[j]+=Num[k]; for(intj=1; j<=tmp; J + +) Num[j]+=num[j],ans[j]+=num[j],s[j]+=tim[j]*Tim[j], Tim[j]+=tim[j],tim[j]=0, num[j]=0; } num[0]=1; intzz=0, ss=Now ; for(intI=fa[now];!visit[i]; Ss=i,i=Fa[i]) {tmp=0; zz++; for(intJ=head[i]; J j=edge[j].next)if(Edge[j].to!=fa[i] &&!visit[edge[j].to] && edge[j].to!=ss) Deep[edge[j].to]=1, Dfsdeep (edge[j].to,i); if(Tmp>maxd) Maxd=tmp; for(intj=1; j<=tmp; J + +) for(intK=j; k<=tmp; k+=j) Tim[j]+=Num[k]; intTt=tmp<block?Tmp:block; for(intj=1; j<=tt; J + +) { if(f[j][zz%j]==-1) {F[j][zz%j]=0; for(intk= (j-zz%j)%j; k<=maxd; k+=j) F[j][zz%j]+=Num[k]; } S[j]+=f[j][zz%j]*Tim[j]; } for(intj=block+1; j<=tmp; J + +) for(intk= (j-zz%j)%j; k<=maxd; k+=j) S[j]+=num[k]*Tim[j]; for(intj=1; j<=tmp; J + +) tim[j]=0, num[j]=0; ANS[ZZ]++; } intL=1, r=0; Long Longtmpans=0; for(intI=2; i<=zz+maxd; i++) Tmpans+=r+1<i? NUM[++R]:0, Tmpans-=l+zz<i? Num[l++]:0, ans[i]+=Tmpans; intTt=maxd<block?Maxd:block; for(intI=1; i<=tt; i++) for(intj=0; j<=i-1; J + +) F[i][j]=-1; for(intI=0; i<=maxd; i++) tim[i]=0, tim[i]=0; for(intI=head[now]; I I=edge[i].next)if(!Visit[edge[i].to]) {Root=0; Siz=Size[edge[i].to]; Getroot (Edge[i].to,now); Getans (root); }}voidFreopen () {freopen ("treegcd.in","R", stdin); Freopen ("Treegcd.out","W", stdout);}voidFclose () {Fclose (stdin); Fclose (stdout);}intMain () {n=read (); Block= (int) sqrt (n); for(intX,i=1; i<=n-1; i++) x=read (), insert (x,i); Maxx[root]=0x7fffffff; Siz=n; memset (f,-1,sizeof(f)); Getroot (1,0); Getans (root); for(inti=n-1; I i--) {Ans[i]=S[i]; for(intJ=i+i; j<=n-1; j+=i) ans[i]-=Ans[j]; } for(intI=1; i<=n-1; i++) printf ("%i64d\n", ans[i]+Ans[i]); return 0;}
Uoj ur#2 Tree gcd (cache)