太妙了卧槽
首先除了1之外其它n-1个点全都等价。
我们假装选定了一个目标点。将它拎出来。
剩下还有n-1个点。这些点在原图上会构成一个最短路树。
我们通过动态规划来算这个树。
我们设f[i][j]表示最后一层用了j个点,当前已经用了i个点的概率。e[i][j]表示期望。
我们可以通过枚举下一层用了多少个点来转移这个概率和期望。
我们考虑转移条件。
首先,下一层任何一个点都得和本层中的某个点连边。
其次,除下一层之外不能再有任何一个点和本层点连边。否则他们也会加入下一层。
第一个概率是(1-{不通概率}^{本层点数})^{下层点数}。设p为联通概率,本层点j个,下层点k个。则第一个概率表达为
总概率减去和本层点都不联通的概率再自乘k次。
第二个概率是,因为这两部分点任何点对都不能有。
与此同时,点号对答案有贡献。所以要从(n-i-1),即减去已经使用和目标答案点之外的剩下点钟,选出k个来给这层标号。
所以概率相乘再乘上一个。而期望的转移本应该是转移概率*(上层期望+1),打开之后发现是转移概率*上层期望+转移概率。因为这道题边权为1比较特殊。
所以直接乘上转移。
统计答案的时候分两部分考虑。一个是联通答案。一个是不连通的1e9答案。
我们不需要枚举从第几层转移过来。因为这些都在转移过程中计算成概率和期望了。我们只需要管总共用了几个点,最后一层有几个点。
对于一个(i,j),最后一层j个点只要有一个和当前点相连就能得到贡献。
所以概率是。同样,也要乘上(概率+期望)。
如果一个都不相连,而本层是最后一层,不能产生下一层。所以n-i个点和这j个点不能产生任何一条边。
概率,贡献是1e9。
这道题的思想本身是bfs树概率期望,我将之视为最短路树,按深度分层。计算出所有可能的概率和期望,最后假设一个最后一层。统计答案。
这种思想值得学习,在点数上思考。
我们发现楼上好像没有直接用p的幂,那就直接预处理的幂就可以了。
其它两道题好像不太可做的鸭子,,
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define in read()
int in{
int cnt=0,f=1;char ch=0;
while(!isdigit(ch)){
ch=getchar();if(ch=='-')f=-1;
}
while(isdigit(ch)){
cnt=cnt*10+ch-48;
ch=getchar();
}return cnt*f;
}
int n,p;
int ri[200003];
int f[403][403],e[403][403],c[403][403];
const int mod=998244353;
int inf=1e9;
int add(int a,int b){
if(a+b>mod)return a+b-mod;return a+b;
}
int dec(int a,int b){
if(a-b<0)return a-b+mod;return a-b;
}
int mul(int a,int b){
return a*b%mod;
}
int ksm(int a,int b){
int sum=1;
while(b){
if(b&1)sum=mul(sum,a);a=mul(a,a);b>>=1;
}return sum;
}
signed main(){
n=in;p=in;p=mul(p,ksm(1000000,mod-2));
for(int i=0;i<=n;i++)c[i][0]=1;
for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)c[i][j]=add(c[i-1][j],c[i-1][j-1]);
ri[0]=1;for(int i=1;i<=200000;i++)ri[i]=ri[i-1]*(1+mod-p)%mod;
f[1][1]=1;e[1][1]=0;
for(int i=1;i<=n-1;i++){
for(int j=1;j<=i;j++){
for(int k=1;k<=n-i-1;k++){
int gu=mul(mul(ksm(dec(1,ri[j]),k),ri[j*(n-i-k)]),c[n-i-1][k]);
f[i+k][k]=add(f[i+k][k],mul(gu,f[i][j]));
e[i+k][k]=add(e[i+k][k],mul(gu,add(f[i][j],e[i][j])));
}
}
}int ans=0;
for(int i=1;i<=n-1;i++){
for(int j=1;j<=i;j++){
ans=add(ans,mul(dec(1,ri[j]),add(f[i][j],e[i][j])));
ans=add(ans,mul(ri[(n-i)*j],mul(f[i][j],inf%mod)));
}
}
cout<<mul(ans,mul(n-1,ksm(10,6*n*n)));
return 0;
}