由于求最短路,边权为
1
1
1,那么考虑在
b
f
s
bfs
bfs树上
d
p
dp
dp,类似于模拟
b
f
s
bfs
bfs树的生成过程。用
f
[
i
]
[
j
]
f[i][j]
f[i][j]表示当前的
b
f
s
bfs
bfs树上一共有
i
i
i个点,最后一层有
j
j
j个点的状态的概率(
i
i
i中包含了
j
j
j),这里最后一层是指只考虑到对应的层,后面的连边还不确定。
d
e
p
[
i
]
[
j
]
dep[i][j]
dep[i][j]代表这样状态的期望深度。我们现在假设选中某一个确定的点,也就是说它的标号确定。因为除了一号点的期望是0,其它点的期望是相同的,那么我们最后给这个点的期望乘上
n
−
1
n
\frac{n-1}{n}
nn−1就是答案了。
考虑从
f
[
i
]
[
j
]
f[i][j]
f[i][j]转移,枚举下一层有几个点,假设有
k
k
k个点。在维护
b
f
s
bfs
bfs树时,有哪些限制条件?
①这
k
k
k个点的每个点和最后一层的
j
j
j个点至少有一条连边,不然
b
f
s
bfs
bfs不到它。
②除去
b
f
s
bfs
bfs树上的
i
i
i个点以及这
k
k
k个点,剩下的所有点和
b
f
s
bfs
bfs树上的这
i
i
i个点不能有连边,不然就会
b
f
s
bfs
bfs到这些剩下的点,导致
b
f
s
bfs
bfs树最后一层不止
k
k
k个点。
③给这
k
k
k个点分配标号时,从
n
−
i
−
1
n-i-1
n−i−1个点中选
k
k
k个出来,减一是因为那个确定的点。
那么有:
f
[
i
+
k
]
[
k
]
=
①
∗
②
∗
③
∗
f
[
i
]
[
j
]
f[i+k][k]=①*②*③*f[i][j]
f[i+k][k]=①∗②∗③∗f[i][j]
由于这一步期望深度=(上一步的期望深度+转移贡献)×这个转移的概率。
于是有:
d
e
p
[
i
+
k
]
[
k
]
=
(
d
e
p
[
i
]
[
j
]
+
f
[
i
]
[
j
]
∗
1
)
∗
①
∗
②
∗
③
dep[i+k][k]=(dep[i][j]+f[i][j]*1)*①*②*③
dep[i+k][k]=(dep[i][j]+f[i][j]∗1)∗①∗②∗③
①,②,③可以预处理出来。
然后怎么统计答案呢,考虑
f
[
i
]
[
j
]
f[i][j]
f[i][j]的贡献:
①令最后一层的
j
j
j个点和选定点连通的概率为
P
P
P,那么贡献就是:
P
∗
(
d
e
p
[
i
]
[
j
]
+
f
[
i
]
[
j
]
∗
1
)
P*(dep[i][j]+f[i][j]*1)
P∗(dep[i][j]+f[i][j]∗1)
②从这个地方开始,后面就不连通了,令最后一层的
j
j
j个点和剩下的
n
−
i
n-i
n−i个点都不联通概率为
Q
Q
Q,那么贡献就是:
f
[
i
]
[
j
]
∗
Q
∗
i
n
f
f[i][j]*Q*inf
f[i][j]∗Q∗inf。
为什么是和
n
−
i
n-i
n−i个点不连通,而不是和选定点不连通?因为
f
f
f并没有把后面的状态确定下来,所以现在是强制把后面断掉,
b
f
s
bfs
bfs树就确定了。不然会算重的。
#include<bits/stdc++.h>
#define cs const
#define re register
cs int N=4e2+10,mod=998244353,oo=1e9;
int f[N][N],dep[N][N],plink[N][N],pcut[N][N],n,p;
int fac[N],ifac[N],ans=0;
inline int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
inline int dec(int x,int y){return x-y<0?x-y+mod:x-y;}
inline int mul(int x,int y){return 1ll*x*y%mod;}
inline void Inc(int &x,int y){x=(x+y>=mod?x+y-mod:x+y);}
inline int quickpow(int a,int b,int ret=1){for(;b;b>>=1,a=mul(a,a))if(b&1)ret=mul(ret,a);return ret;}
inline void prework(){
fac[0]=1;
for(int i=1;i<N;++i) fac[i]=mul(fac[i-1],i);
ifac[N-1]=quickpow(fac[N-1],mod-2);
for(int i=N-2;~i;--i) ifac[i]=mul(ifac[i+1],i+1);
for(int i=1;i<N;++i)
for(int j=0;j<N;++j)
pcut[i][j]=quickpow(dec(1,p),i*j),
plink[i][j]=quickpow(dec(1,quickpow(dec(1,p),i)),j);
}
inline int C(int n,int m){return n<m?0:mul(fac[n],mul(ifac[m],ifac[n-m]));}
int main(){
scanf("%d%d",&n,&p),p=mul(p,quickpow(1000000,mod-2));
prework(),f[1][1]=1,dep[1][1]=0;
for(int i=1;i<=n-1;++i){
for(int j=1;j<=i;++j) if(f[i][j]){
for(int k=1;k+i+1<=n;++k){
int tmp=mul(plink[j][k],mul(C(n-i-1,k),pcut[j][n-i-k]));
Inc(f[i+k][k],mul(tmp,f[i][j]));
Inc(dep[i+k][k],mul(tmp,add(dep[i][j],f[i][j])));
}
}
}
for(int i=1;i<=n-1;++i){
for(int j=1;j<=i;++j) if(f[i][j]){
Inc(ans,mul(plink[j][1],add(dep[i][j],f[i][j])));
Inc(ans,mul(mul(pcut[j][n-i],f[i][j]),oo%mod));
}
}printf("%d\n",mul(mul(ans,n-1),quickpow(10,6*n*n)));
}