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$的题还设成权限题.. 首先我们考虑期望的线性性,即考虑每个点的贡献. 显然每个点的贡献就是它在点分树上的深度,所以 ...
随机推荐
- SSL学习笔记
/************************************数据类型***************************************//* Number(数值型),Bool ...
- Java多线程实现异步调用
在Java平台,实现异步调用的角色有如下三个角色:调用者. 提货单 .真实数据,一个调用者在调用耗时操作,不能立即返回数据时,先返回一个提货单 .然后在过一断时间后凭提货单来获取真正的数据.去蛋糕店买 ...
- Python爬虫之Cookie和Session
关于cookie和session估计很多程序员面试的时候都会被问到,这两个概念在写web以及爬虫中都会涉及,并且两者可能很多人直接回答也不好说的特别清楚,所以整理这样一篇文章,也帮助自己加深理解 什么 ...
- css四种选择器总结
css 在网页开发中扮演着重要的角色,被誉为网页开发的三剑客,如果说html是人的外在器官部分,那css无疑是各个器官组成在一起然后表现出来,css又称样式重叠在网页排版布局中的地位举足轻重. 做 ...
- 02--STL算法(函数对象和谓词)
一:函数对象(仿函数):实现状态记录等其他操作<相对于普通函数> 重载函数调用操作符的类,其对象常称为函数对象(function object),即它们是行为类似函数的对象. 即是重载了“ ...
- VSTO学习(六)——创建Outlook解决方案
本专题概要 引言 Outlook对象模型 自定义Outlook窗体 小结 一.引言 在上一个专题中,为大家简单介绍了下如何创建Word解决方案的,所以本专题中将为大家介绍下Outlook相关的内容.我 ...
- SqlServer内存占用查看
查看每个数据库对内存的占用 SELECT ISNULL(DB_NAME(DATABASE_ID),'RESOURCEDB') AS DATABASENAME, ,)) AS 'SIZE(MB)' FR ...
- CentOS 安装Scrapy
本文python版本是python3.5.3,关于升级python和安装pip请到:http://www.cnblogs.com/technologylife/p/6242115.html 安装相关包 ...
- Gen中的switch分析及lookupswitch与tableswitch指令
int chooseNear(int i) { switch (i) { case 0: return 0; case 1: return 1; case 2: return 2; default: ...
- javascript 数组去重的6种思路
前端在日常开发中或多或少都会碰到有对数据去重的需求,实际上,像是lodash这些工具库已经有成熟完备的实现,并且可以成熟地运用于生产环境.但是这并不妨碍我们从思维拓展的角度出发,看看去重可以用几种思路 ...