[UOJ#351]新年的叶子
[UOJ#351]新年的叶子
试题描述
躲过了AlphaGo 之后,你躲在 SingleDog 的长毛里,和它们一起来到了AlphaGo 的家。此时你们才突然发现,AlphaGo 的家居然是一个隐藏在地下的计算中心!难道 AlphaGo 如此人赢的秘密是...它其实是一个 AI?
根据情报,这个地下的计算中心的结构构成了一棵无根树,整个计算中心名为被 AT-field 的力场保护起来,保护力场的直径恰好等于树的直径(树的直径定义为树上距离最远的两个结点之间的距离,结点 \(u,v\) 的距离定义为从 \(u\) 到 \(v\) 最少需要经过的边数)。
由于保护力场的存在,SingleDog 们每次只能进入整棵树的一个叶子(度为 \(1\) 的结点),由于狗的大脑很小,他们每次只会随机进攻一个原树的叶子,并且破坏里面的设备,更加狼狈的是他们甚至会重复进入一个已经被破坏过的叶子。

比如这棵树中,SingleDog 们攻击的就是 \(3,4,7\) 这三个点,他们不会攻击 \(2\) 号点,因为它不是原树的叶子。
他们想知道,期望多少次之后,可以使得保护力场的直径缩小?
即,对于一棵树,每次随机染黑一个叶子(可能会重复染黑),期望多少次后直径变小?
输入
从标准输入读入数据。
第一行一个正整数 \(n\),表示树的点数。
接下来 \(n−1\) 行,每行两个正整数 \(x,y\),表示树上的一条边。
输出
输出到标准输出。
输出一行一个整数表示答案在模 \(998244353\) 意义下的取值。
即设答案化为最简分式后的形式为 \(\frac{a}{b}\) ,其中 \(a\) 和 \(b\) 互质。输出整数 \(x\) 使得 \(bx \equiv a(\mod 998244353)\) 且 \(0 \le x < 998244353\)。可以证明这样的整数 \(x\) 是唯一的。
输入示例1
3
1 2
2 3
输出示例1
1
输入示例2
6
1 2
2 3
1 4
4 5
1 6
输出示例2
499122178
数据规模及约定
对于所有数据,\(3 \le n \le 5 \times 10^5\),\(1 \le x,y \le n\)。
题解
首先考虑一下直径的性质,若直径长度为偶数条边,所有直径的中点是相同的;否则所有直径最中间那条边是相同的。
令 \(l\) 为直径长度。
那么对于偶数的情况,我们将 \(u\) 的每个儿子中深度为 \(\frac{l}{2}\) 的所有叶子放在一个集合当中,这样当染到只有一个集合内还有未被染黑的叶子时直径一定变短了;
若 \(l\) 为奇数,那么所有深度为 \(\frac{l+1}{2}\) 的叶子一定在同一个子树中,把所有不在那个子树中的深度为 \(\frac{l-1}{2}\) 的叶子放到一个集合中就可以按照和偶数情况一样处理了。
现在需要把问题转化一下,把“每次可以染黑点”改成“每次一定染白点”,但是这样改之后每一步的期望不再是 \(1\) 了,所以我们令这个期望是 \(x\),然后尝试计算出来。
具体来说,现在有 \(n\) 个叶子,有 \(m\) 个白的,其余都是黑的,那么染一个白色叶子需要期望多少步。考虑下一步染色的两种情况,分别是染黑色叶子和染白色叶子,两种情况概率分别是 \(\frac{n-m}{n}\) 和 \(\frac{m}{n}\),如果染白色叶子那么目标已经完成,所以期望步数是 \(1\),否则相当于没做任何操作,所以期望步数还是 \(x\),所以我们可以列一个方程
\]
解得 \(x = \frac{n}{m}\)。
现在我们枚举集合 \(x\),假装它最终没有被染黑(即忽略掉它),在这种情况下染黑其它所有集合中的节点的期望步数是多少?很显然就是每一步的期望的叠加,令 \(N\) 表示总叶子数,\(S\) 表示所有集合中叶子的总数,期望步数就是 \(\sum_{i=1}^{S - |x|} \frac{N}{i}\),这里就是将关系的点看成白色,忽略的点看成黑色。
如果我们将对于所有 \(x\) 的这个期望直接累加肯定不是答案,它算多了。这是因为我们那么算期望步数的时候并没有考虑集合 \(x\) 内的叶子的染色情况,也就是说它们被全部染黑的情况也被统计进去了;所以我们多算的部分就是所有集合中的叶子都染黑的情况。注意到只有在最后一步染黑的集合不是 \(x\) 的时候才会多算,也就是说在枚举到集合 \(x\) 的时候我们多算的是 \(\sum_{y \ne x} 最后一步将集合\ y\ 染黑,使得所有集合中的叶子全黑的期望步数\)。那么多算的部分就是(令集合个数为 \(T\),\(E(y)\) 表示“最后一步将集合 \(y\) 染黑,使得所有集合中的叶子全黑的期望步数”)
= \sum_y E(y) \sum_{x \ne y} 1 \\
= \sum_y E(y) \cdot (T - 1) \\
= (T - 1) \sum_y E(y)
\]
所以多算的就是 \((T-1)\) 倍的将所有集合中的叶子染黑的期望步数,最后减去这个数就好了。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
using namespace std;
#define rep(i, s, t) for(int i = (s), mi = (t); i <= mi; i++)
#define dwn(i, s, t) for(int i = (s), mi = (t); i >= mi; i--)
int read() {
int x = 0, f = 1; char c = getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
return x * f;
}
#define maxn 500010
#define maxm 1000010
#define MOD 998244353
#define LL long long
int n, m, head[maxn], nxt[maxm], to[maxm], deg[maxn];
void AddEdge(int a, int b) {
to[++m] = b; nxt[m] = head[a]; head[a] = m;
swap(a, b);
to[++m] = b; nxt[m] = head[a]; head[a] = m;
deg[a]++; deg[b]++;
return ;
}
int step[maxn], fa[maxn], Q[maxn], hd, tl;
int BFS(int s) {
memset(step, -1, sizeof(step));
hd = tl = 0; Q[++tl] = s; step[s] = 0; fa[s] = 0;
while(hd < tl) {
int u = Q[++hd];
for(int e = head[u]; e; e = nxt[e]) if(step[to[e]] < 0) {
step[to[e]] = step[u] + 1;
fa[to[e]] = u;
Q[++tl] = to[e];
}
}
int mx = 0, mxi;
rep(i, 1, n) if(step[i] > mx) mx = step[i], mxi = i;
return mxi;
}
int mxh[maxn], tot[maxn];
void dp(int u, int pa) {
mxh[u] = 0; tot[u] = 1;
for(int e = head[u]; e; e = nxt[e]) if(to[e] != pa) {
dp(to[e], u);
if(mxh[to[e]] + 1 == mxh[u]) tot[u] += tot[to[e]];
else if(mxh[to[e]] + 1 > mxh[u]) mxh[u] = mxh[to[e]] + 1, tot[u] = tot[to[e]];
}
return ;
}
int siz[maxn], cnts, inv[maxn], sum[maxn];
int main() {
n = read();
rep(i, 1, n - 1) {
int a = read(), b = read();
AddEdge(a, b);
}
int A = BFS(1), B = BFS(A), len = step[B];
rep(i, 1, len >> 1) B = fa[B];
dp(B, 0);
for(int e = head[B]; e; e = nxt[e]) if(mxh[to[e]] + 1 == (len + 1 >> 1)) siz[++cnts] = tot[to[e]];
if(len & 1) {
cnts++;
for(int e = head[B]; e; e = nxt[e]) if(mxh[to[e]] + 1 == (len >> 1)) siz[cnts] += tot[to[e]];
}
int N = 0, sn = 0;
rep(i, 1, n) N += deg[i] == 1;
rep(i, 1, cnts) sn += siz[i];
inv[1] = 1;
rep(i, 2, N) inv[i] = (LL)(MOD - MOD / i) * inv[MOD%i] % MOD;
sum[0] = 0;
rep(i, 1, n) {
sum[i] = sum[i-1] + (LL)N * inv[i] % MOD;
if(sum[i] >= MOD) sum[i] -= MOD;
}
int ans = 0;
rep(i, 1, cnts) {
ans += sum[sn-siz[i]];
if(ans >= MOD) ans -= MOD;
}
ans -= (LL)(cnts - 1) * sum[sn] % MOD;
if(ans < 0) ans += MOD;
printf("%d\n", ans);
return 0;
}
[UOJ#351]新年的叶子的更多相关文章
- UOJ#351. 新年的叶子 概率期望
原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ351.html 题目传送门 - UOJ351 题意 有一个 n 个节点的树,每次涂黑一个叶子节点(度为 1 ...
- uoj#351. 新年的叶子(概率期望)
传送门 数学还是太差了,想了半天都没想出来 首先有一个定理,如果直径(这里考虑经过的点数)为奇数,所有直径有同一个中点,如果直径为偶数,所有直径有同一条最中间的边.这个可以用反证法,假设不成立的话直径 ...
- 「UOJ351」新年的叶子
「UOJ351」新年的叶子 题目描述 有一棵大小为 \(n\) 的树,每次随机将一个叶子染黑,可以重复染,问期望染多少次后树的直径会缩小. \(1 \leq n \leq 5 \times 10^5\ ...
- 【UOJ 351】新年的叶子
http://uoj.ac/problem/351 其实原来看到这题是真的不想做的 毕竟真的特别怕期望题 后来莫名发现自己打了正解 也是很震惊的2333 Description 对于一棵树,每次随 ...
- 【UOJ #351】新年的叶子(树的直径,期望)
题目链接 这的确是一道好题,我们不妨依循思路一步步推导,看问题是如何被解决的. 做一些约定,设$m$为树的叶子节点个数,设$len$为该树的直径(经过的点数). 毫无疑问,直径可能有多条,我们需要把所 ...
- uoj#67. 新年的毒瘤(割顶)
#67. 新年的毒瘤 辞旧迎新之际,喜羊羊正在打理羊村的绿化带,然后他发现了一棵长着毒瘤的树. 这个长着毒瘤的树可以用n个结点m 条无向边的无向图表示.这个图中有一些结点被称作是毒瘤结点,即删掉这个结 ...
- uoj 67 新年的毒瘤 tarjan求割点
#67. 新年的毒瘤 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://uoj.ac/problem/67 Description 辞旧迎新之际 ...
- uoj 66 新年的巧克力棒 数学
#66. 新年的巧克力棒 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://uoj.ac/problem/66 Description 马上就要 ...
- UOJ#67. 新年的毒瘤
传送门 练习一下Tarjan的模板. 求一下割点,然后加个约束条件判一下特殊点,剩下的就是所求点. //UOJ 67 //by Cydiater //2016.10.27 #include <i ...
随机推荐
- 一些斗鱼TV Web API [Some DouyuTv API]
一些斗鱼TV Web API [Some DouyuTv API] 写在最前 去年TI5前开发了dotaonly.com,网站需要用到各个直播平台API.不像国外网站Twitch那样开放,都有现成 ...
- Django admin操作
无名小妖 昵称:无名小妖园龄:1年6个月粉丝:22关注:1 +加关注 搜索 常用链接 我的随笔 我的评论 我的参与 最新评论 我的标签 我的标签 Python(1) python3 ...
- 3招搞定APP注册作弊
在说如何应对之前,易盾先给各位盾友梳理移动端APP可能遇到哪些作弊风险.1. 渠道商刷量,伪造大量的下载量和装机量,但没有新用户注册:2. 对于电商.P2P.外卖等平台,会面临散户或者团队刷子的注册- ...
- js字符编码笔记
一. 什么是unicode? ascii码能表示的字符非常有限(128个字符),这对英文来说足够了,但是对法文.中文.土耳奇文等文字则远远不够,于是就产生了新的编码规则-unicode,unicod ...
- 阅读MDN文档之布局(四)
Introducing positioning Static positioning Relative positioning Introducing top, bottom, left and ri ...
- windows中vim以及cmder的使用
虽然有gvim,但是我依然更喜欢控制台(可理解为博主的偏执已经发展到某个阶段). windows自带的控制台很糟糕,尤其是我正在用的win7竟然没有全屏功能.任何一个占领屏幕的图标显然是不可忍受的. ...
- Qt Qwdget 汽车仪表知识点拆解2 图像放大
先贴上效果图,注意,没有写逻辑,都是乱动的 这里讲下 这个小汽车的进入过程,其实这个说白了就没有技术含量了,本来应该趁着这个机会学习一下Qt的动画机制,不过随机一想,这个自己写也累不到那里去 下面说下 ...
- PHP实现字节数Byte转换为KB、MB、GB、TB
function getFilesize($num) { $p = 0; $format = 'bytes'; if( $num > 0 && $num < 1024 ) ...
- 《python机器学习—预测分析核心算法》:理解数据
参见原书2.1-2.2节 新数据集就像一个包装好的礼物,它充满了承诺和希望! 但是直到你打开前,它都保持神秘! 一.基础问题的架构.术语,机器学习数据集的特性 通常,行代表实例,列代表属性特征 属性, ...
- 机器学习实战一:kNN手写识别系统
实战一:kNN手写识别系统 本文将一步步地构造使用K-近邻分类器的手写识别系统.由于能力有限,这里构造的系统只能识别0-9.需要识别的数字已经使用图形处理软件,处理成具有相同的色彩和大小:32像素*3 ...