hihoCoder #1047 Random Tree
题意
给出点数为
解法
固定两点
、 , ,
第1类边出现在
每个第2类边出现在
考虑第3类边(对期望)的贡献。
首先应当注意到,所有第3类边出现在
用
我们分 3 步来求
-
固定
,将 缩成一点 ,加上余下的 个点,就得到一棵 个点的树 。 -
将
的度数固定为 ,对应的生成树 的数目 的表达式为
式可通过 Prufer 序列与树的一一对应关系得到。 -
与
相连的 棵子树中的每一棵,在 中可以连在 上的 个点中的任意一个,所以我们得到
从而
Implementation
#include <bits/stdc++.h>
using namespace std;
using DB=long double;
const int N=1005;
DB res[N][N];
int a[N][N];
DB calc(int n){
if(n<=3) return 0;
DB pn=1;
for(int i=1; i<=n-2; i++)
pn*=i, pn/=n;
// cout << pn << endl;
DB sum=pn*(n-3);
for(int i=n-1; i>=4; i--)
pn*=n*i, pn/=(n-i)*(i+1), sum+=pn*(i-3);
return sum;
}
int main(){
// int cnt=0;
// for(int i=0; i<=1000; i++)
// cnt+=fabs(t[i]-calc(i))>1e-50;
// cout << cnt << endl;
int n, tot=0;
scanf("%d", &n);
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
scanf("%d", a[i]+j), a[i][0]+=a[i][j], tot+=a[i][j];
tot/=2;
DB x=calc(n);
for(int i=1; i<n; i++)
for(int j=i+1; j<=n; j++){
res[i][j]=(a[i][0]+a[j][0])/DB(n);
if(n>=4) // 注意:n=2 或 3 时,分母为 0
res[i][j]+=x*(tot-a[i][0]-a[j][0]+a[i][j])/((n-2)*(n-3)/2);
res[j][i]=res[i][j];
}
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
printf("%.9Lf%c", res[i][j], j==n?'\n':' ');
return 0;
}
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
· dotnet 源代码生成器分析器入门
· ThreeJs-16智慧城市项目(重磅以及未来发展ai)
· .NET 原生驾驭 AI 新基建实战系列(一):向量数据库的应用与畅想
· Ai满嘴顺口溜,想考研?浪费我几个小时
· Browser-use 详细介绍&使用文档
· 软件产品开发中常见的10个问题及处理方法