BZOJ3451:Tyvj1953 Normal
根据期望的线性性,答案就是 \(\sum\) 每个连通块出现次数的期望
而每个连通块次数的期望就是 \(\sum\) 连通块的根与每个点连通次数的期望
也就是对于一条路径 \((i,j)\),设 \(i\) 为根,那么 \(i\) 必须是这条路径第一个被选择的点,概率为 \(\frac{1}{dis(i,j)}\),其中 \(dis(i,j)\) 表示 \((i,j)\) 上的点数
那么只要统计不同的 \(dis(i,j)\) 的个数即可
直接点分治+\(FFT\)
# include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn(1 << 18);
const int mod(998244353);
inline void Inc(int &x, int y) {
x = x + y >= mod ? x + y - mod : x + y;
}
inline void Dec(int &x, int y) {
x = x - y < 0 ? x - y + mod : x - y;
}
inline int Add(int x, int y) {
return x + y >= mod ? x + y - mod : x + y;
}
inline int Sub(int x, int y) {
return x - y < 0 ? x - y + mod : x - y;
}
inline int Pow(ll x, int y) {
register ll ret = 1;
for (; y; y >>= 1, x = x * x % mod)
if (y & 1) ret = ret * x % mod;
return ret;
}
int w[2][maxn], a[maxn], b[maxn], len, l, r[maxn];
inline void Init(int n) {
int i, x, y;
for (l = 0, len = 1; len < n; len <<= 1) ++l;
for (i = 0; i < len; ++i) r[i] = (r[i >> 1] >> 1) | ((i & 1) << (l - 1));
x = Pow(3, (mod - 1) / len), y = Pow(x, mod - 2), w[0][0] = w[1][0] = 1;
for (i = 1; i < len; ++i) w[0][i] = (ll)w[0][i - 1] * x % mod, w[1][i] = (ll)w[1][i - 1] * y % mod;
for (i = 0; i < len; ++i) a[i] = b[i] = 0;
}
inline void DFT(int *p, int opt) {
int i, j, k, x, y, t;
for (i = 0; i < len; ++i) if (i < r[i]) swap(p[i], p[r[i]]);
for (i = 1; i < len; i <<= 1)
for (j = 0, t = i << 1; j < len; j += t)
for (k = 0; k < i; ++k) {
x = p[j + k], y = (ll)w[opt == -1][len / t * k] * p[j + k + i] % mod;
p[j + k] = Add(x, y), p[j + k + i] = Sub(x, y);
}
if (opt == -1) for (i = 0, t = Pow(len, mod - 2); i < len; ++i) p[i] = (ll)p[i] * t % mod;
}
int n, first[maxn], cnt, cur[maxn], size[maxn], mx[maxn], vis[maxn], rt, sz, deep[maxn], mxd;
long double ans;
struct Edge {
int to, next;
} edge[maxn << 1];
inline void AddEdge(int u, int v) {
edge[cnt] = (Edge){v, first[u]}, first[u] = cnt++;
edge[cnt] = (Edge){u, first[v]}, first[v] = cnt++;
}
void Getroot(int u, int ff) {
int e, v;
size[u] = 1, mx[u] = 0;
for (e = first[u]; ~e; e = edge[e].next)
if ((v = edge[e].to) != ff && !vis[v]) {
Getroot(v, u);
size[u] += size[v];
mx[u] = max(mx[u], size[v]);
}
mx[u] = max(mx[u], sz - size[u]);
if (mx[u] < mx[rt]) rt = u;
}
void Getdeep(int u, int ff, int d) {
int e, v;
++deep[d], mxd = max(mxd, d);
for (e = first[u]; ~e; e = edge[e].next)
if ((v = edge[e].to) != ff && !vis[v]) Getdeep(v, u, d + 1);
}
void Solve(int u) {
int e, v, i, len1, len2;
mxd = 0, Getdeep(u, 0, 0), vis[u] = 1;
Init((mxd << 1) + 1), len1 = mxd << 1;
for (i = 0; i <= mxd; ++i) a[i] = deep[i], deep[i] = 0;
DFT(a, 1), len2 = len;
for (i = 0; i < len2; ++i) a[i] = (ll)a[i] * a[i] % mod;
DFT(a, -1);
for (i = 0; i <= len1; ++i) Inc(cur[i + 1], a[i]);
for (e = first[u]; ~e; e = edge[e].next)
if (!vis[v = edge[e].to]) {
mxd = 0, Getdeep(v, u, 1), Init(mxd << 1 | 1), len1 = mxd << 1;
for (i = 0; i <= mxd; ++i) b[i] = deep[i], deep[i] = 0;
DFT(b, 1);
for (i = 0; i < len; ++i) b[i] = (ll)b[i] * b[i] % mod;
DFT(b, -1);
for (i = 0; i <= len1; ++i) Dec(cur[i + 1], b[i]);
}
for (e = first[u]; ~e; e = edge[e].next)
if (!vis[v = edge[e].to]) {
rt = 0, sz = size[v];
Getroot(v, u), Solve(rt);
}
}
int main() {
int i, j, k, u, v;
memset(first, -1, sizeof(first));
scanf("%d", &n);
for (i = 1; i < n; ++i) scanf("%d%d", &u, &v), AddEdge(u + 1, v + 1);
sz = n, mx[0] = n + 1, Getroot(1, 0), Solve(rt);
for (i = 1; i <= n; ++i) if (cur[i]) ans += 1.0 * cur[i] / (1.0 * i);
printf("%.4Lf\n", ans);
return 0;
}
BZOJ3451:Tyvj1953 Normal的更多相关文章
- 【BZOJ3451】Tyvj1953 Normal 点分治+FFT+期望
[BZOJ3451]Tyvj1953 Normal Description 某天WJMZBMR学习了一个神奇的算法:树的点分治!这个算法的核心是这样的:消耗时间=0Solve(树 a) 消耗时间 += ...
- 【bzoj3451】Tyvj1953 Normal 期望+树的点分治+FFT
题目描述 给你一棵 $n$ 个点的树,对这棵树进行随机点分治,每次随机一个点作为分治中心.定义消耗时间为每层分治的子树大小之和,求消耗时间的期望. 输入 第一行一个整数n,表示树的大小接下来n-1行每 ...
- 【BZOJ3451】Tyvj1953 Normal - 点分治+FFT
题目来源:NOI2019模拟测试赛(七) 非原题面,题意有略微区别 题意: 吐槽: 心态崩了. 好不容易场上想出一题正解,写了三个小时结果写了个假的点分治,卡成$O(n^2)$ 我退役吧. 题解: 原 ...
- BZOJ3451: Tyvj1953 Normal
题解: 好神的一道题.蒟蒻只能膜拜题解. 考虑a对b的贡献,如果a是a-b路径上第一个删除的点,那么给b贡献1. 所以转化之后就是求sigma(1/dist(i,j)),orz!!! 如果不是分母的话 ...
- bzoj 3451: Tyvj1953 Normal [fft 点分治 期望]
3451: Tyvj1953 Normal 题意: N 个点的树,点分治时等概率地随机选点,代价为当前连通块的顶点数量,求代价的期望值 百年难遇的点分治一遍AC!!! 今天又去翻了一下<具体数学 ...
- BZOJ3451 Tyvj1953 Normal 点分治 多项式 FFT
原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ3451.html 题目传送门 - BZOJ3451 题意 给定一棵有 $n$ 个节点的树,在树上随机点分 ...
- [BZOJ3451][Tyvj1953]Normal(点分治+FFT)
https://www.cnblogs.com/GXZlegend/p/8611948.html #include<cmath> #include<cstdio> #inclu ...
- BZOJ3451 Tyvj1953 Normal 【期望 + 点分治 + NTT】
题目链接 BZOJ3451 题解 考虑每个点产生的贡献,即为该点在点分树中的深度期望值 由于期望的线性,最后的答案就是每个点贡献之和 对于点对\((i,j)\),考虑\(j\)成为\(i\)祖先的概率 ...
- tyvj1953 Normal
题目链接 正解:点分治+$FFT$. 很想吐槽一下$bzoj$,为什么搬了别的$oj$的题还设成权限题.. 首先我们考虑期望的线性性,即考虑每个点的贡献. 显然每个点的贡献就是它在点分树上的深度,所以 ...
随机推荐
- kali Linux 上编译并使用RFID核弹——proxmark3
你还在在Windows下使用proxmark3?弱爆了! 本文作者:i春秋签约作家——冰尘 作为一个标准的日天日地日空气的(单身贵族泰迪)物理黑客Proxmark3这么高大上的东西应该是在键盘敲打声中 ...
- echart 遇到的点
1,图表随着外部container变化而变化: window.onresize = myChart.resize (拿着resize在api文档中搜就看到了)
- Flask从入门到精通之数据模型之间的关系
关系型数据库使用关系把不同表中的行联系起来.上篇随笔中介绍的用户和角色之间是一种简单的关系.即角色到用户的一对多关系,因为一个角色可属于多个用户,而每个用户都只能有一个角色.这种关系在模型中的表示方法 ...
- jvm内存结构(二)(栈的变化,机器指令的格式/执行模式)
栈的结构: <Java虚拟机原理图解>4.JVM机器指令集 局部变量表: 方法执行时,虚拟机会把字节码中方法数据区的code类型的属性中的局部变量放到栈的局部变量表中. 操作栈: jvm指 ...
- OC 中的属性
自动合成 (autosynthesis) @property 语法,会做下面两件事情 自动生成存取方法 由编译器生成,编辑器里不会看到这些方法. 向类中添加适当类型的实例变量 在属性前加下划线,作为实 ...
- 部署虚拟环境安装Linux系统
目录 准备工作 安装linux系统 重置root管理员密码 源代码编译 R ...
- 百度地图笔记_覆盖物(标注marker,折线polyline,多边形polygon)的点击弹窗和右键菜单
利用绘制工具绘制点线面,并在执行绘制完成回调事件给相应覆盖物添加事件操作,提供标注的点击弹窗和标注.折线.多边形的右键删除 效果图如下: 完整代码如下:html+js <!DOCTYPE htm ...
- 【Java并发编程】:volatile变量修饰符
volatile用处说明 在JDK1.2之前,java的内存模型实现总是从主存(即共享内存)读取变量,是不需要进行特别的注意的.而随着JVM的成熟和优化,现在在多线程环境下volatile关键 ...
- C/C++ -- Gui编程 -- Qt库的使用 -- 纯代码实现信号槽
失败,系统找不着槽 #include<QtGui> int main(int argc, char * argv[]) { QApplication app(argc, argv); QT ...
- WebBench压力测试工具
Webbench是有名的网站压力测试工具,它是由 Lionbridge公司(http://www.lionbridge.com)开发. Webbech能测试处在相同硬件上,不同服务的性能以及不同硬件上 ...