题目链接
题目解法
考虑期望的线性性,
A
n
s
=
∑
i
=
1
n
E
(
X
i
)
Ans=\sum\limits_{i=1}^{n}E(X_i)
Ans=i=1∑nE(Xi)
其中
E
(
X
i
)
E(X_i)
E(Xi) 为选
i
i
i 的期望次数
考虑点
i
i
i 有关的点只有它的祖先
因为我们当前求的是
i
i
i 的期望次数,和它祖先选的次数没有关系,所以我们可以考虑忽略 “它或它的任意一个祖先未被选中” 的条件
所以将问题转化成了有
d
e
p
t
h
i
depth_i
depthi 个点,每次随机抽一个点,知道所有点都被抽过(否则之后
i
i
i 也可能被抽),求第
d
e
p
t
h
i
depth_i
depthi 个点被抽的期望次数
考虑当前剩下了
k
k
k 个点,下一个抽到之前未抽过的点的概率是
d
e
p
t
h
i
−
k
d
e
p
t
h
i
\frac{depth_i-k}{depth_i}
depthidepthi−k,所以期望步数为
d
e
p
t
h
i
d
e
p
t
h
i
−
k
\frac{depth_i}{depth_i-k}
depthi−kdepthi
所以抽完
d
e
p
t
h
i
depth_i
depthi 个点的期望步数为
∑
k
=
0
d
e
p
t
h
i
−
1
d
e
p
t
h
i
d
e
p
t
h
i
−
k
\sum\limits_{k=0}^{depth_i-1}\frac{depth_i}{depth_i-k}
k=0∑depthi−1depthi−kdepthi
所以第
i
i
i 个点被抽中的期望次数即为
∑
k
=
0
d
e
p
t
h
i
−
1
1
d
e
p
t
h
i
−
k
=
∑
k
=
1
d
e
p
t
h
i
1
k
\sum\limits_{k=0}^{depth_i-1}\frac{1}{depth_i-k}=\sum\limits_{k=1}^{depth_i}\frac{1}{k}
k=0∑depthi−1depthi−k1=k=1∑depthik1
直接计算即可
时间复杂度
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)
#include <bits/stdc++.h>
using namespace std;
const int N=200100,P=998244353;
int n,d[N];
int e[N<<1],ne[N<<1],h[N],idx;
inline int read(){
int FF=0,RR=1;
char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') RR=-1;
for(;isdigit(ch);ch=getchar()) FF=(FF<<1)+(FF<<3)+ch-48;
return FF*RR;
}
void add(int x,int y){ e[idx]=y,ne[idx]=h[x],h[x]=idx++;}
void dfs(int u){
for(int i=h[u];~i;i=ne[i]) d[e[i]]=d[u]+1,dfs(e[i]);
}
int qmi(int a,int b){
int res=1;
for(;b;b>>=1){
if(b&1) res=1ll*res*a%P;
a=1ll*a*a%P;
}
return res;
}
int main(){
memset(h,-1,sizeof(h));
n=read();
for(int i=2;i<=n;i++){
int fa=read();
add(fa,i);
}
d[1]=1,dfs(1);
h[1]=1;
for(int i=2;i<=n;i++) h[i]=(h[i-1]+qmi(i,P-2))%P;
int ans=0;
for(int i=1;i<=n;i++) ans=(ans+h[d[i]])%P;
printf("%d\n",ans);
fprintf(stderr,"%d ms\n",int(1e3*clock()/CLOCKS_PER_SEC));
return 0;
}