题目(cf)

题目(洛谷)

题目大意

给定 n n n 个节点的无根树,有 k k k 个指定的节点上有蝴蝶。对每条边等概率地指定任意方向,按照边的编号顺序查找每条边,若边 u → v u\to v u→v 满足 u u u 有蝴蝶且 v v v 没有蝴蝶,则蝴蝶从 u u u 飞到 v v v. 求两只蝴蝶之间距离的期望值。

题解

首先要注意,求期望值的两只蝴蝶不是给定的。

显然,这个期望值的求法是每条边的贡献累加,求出所有蝴蝶两两距离和的期望值,再除以选择两只蝴蝶的方案数 C k 2 = k ( k − 1 ) 2 C_k^2=\frac {k(k-1)}{2} Ck2​=2k(k−1)​.

先考虑一个简化的经典问题:蝴蝶不会飞的情况。

枚举每条边,若其左边有 x x x 只蝴蝶,那么其右边有 k − x k-x k−x 只蝴蝶,这条边将会成为 x × ( k − x ) x\times (k-x) x×(k−x) 对蝴蝶之间的路径上的一条边。换一种说法,有 x × ( k − x ) x\times (k-x) x×(k−x) 条路径会经过这条边。那么这条边会对总距离值贡献 x × ( k − x ) x\times (k-x) x×(k−x). 也就是说简化情况下 a n s = ∑ ( u , v ) ∈ M s u m u ( k − s u m u ) k ( k − 1 ) 2 ans=\frac{\sum\limits_{(u,v)\in M}sum_u(k-sum_u)}{\frac{k(k-1)}{2}} ans=2k(k−1)​(u,v)∈M∑​sumu​(k−sumu​)​. s u m i sum_i sumi​ 表示 i i i 的子树中有多少只蝴蝶。这个可以一次dfs O ( n ) O(n) O(n) 求出。

回到原问题。如果我们知道每条边两边分别有多少蝴蝶,则贡献可求。

思考发现对于边 ( u , v ) (u,v) (u,v),不管蝴蝶怎么飞, s u m sum sum 值的变化量最大为 1 1 1. 而 s u m sum sum 是否改变只取决于 u u u 和 v v v 上是否有蝴蝶。这就是说,我们需要求出 u u u 和 v v v 有蝴蝶的概率。设这个概率为 p p p.

考虑对于 p u p_u pu​:

  • 原来 u u u 和 v v v 上都有蝴蝶,则现在 u u u 有蝴蝶的概率为 p u × p v p_u\times p_v pu​×pv​.
  • 原来 u u u 和 v v v 上都没有蝴蝶,则现在 u u u 有蝴蝶的概率为 0 0 0.
  • 原来 u u u 有蝴蝶, v v v 没有,则现在 u u u 有蝴蝶的概率为 p u ( 1 − p v ) 2 \frac {p_u(1-p_v)}{2} 2pu​(1−pv​)​. 因为有 1 2 \frac 1 2 21​ 的概率边 ( u , v ) (u,v) (u,v) 变成 v → u v\to u v→u,只有这样蝴蝶才不会从 u u u 飞到 v v v.
  • 原来 u u u 没有蝴蝶, v v v 有,则现在 u u u 有蝴蝶的概率为 ( 1 − p u ) p v 2 \frac {(1-p_u)p_v}{2} 2(1−pu​)pv​​. 因为有 1 2 \frac 1 2 21​ 的概率边 ( u , v ) (u,v) (u,v) 变成 v → u v\to u v→u,只有这样蝴蝶才会从 v v v 飞到 u u u.

对上述概率求和,得到 u u u 有蝴蝶的概率为 p u p v + p u ( 1 − p v ) 2 + ( 1 − p u ) p v 2 = p u + p v 2 p_up_v+\frac {p_u(1-p_v)}{2}+\frac {(1-p_u)p_v}{2}=\frac {p_u+p_v}{2} pu​pv​+2pu​(1−pv​)​+2(1−pu​)pv​​=2pu​+pv​​.

也就是转移时 p u = p u + p v 2 p_u=\frac {p_u+p_v}{2} pu​=2pu​+pv​​. 对于 p v p_v pv​ 同理,得 p u = p v = p u + p v 2 p_u=p_v=\frac {p_u+p_v}{2} pu​=pv​=2pu​+pv​​.

在修改概率前,我们就需要对边 ( u , v ) (u,v) (u,v) 统计答案。

考虑如下情况:

  • u u u 和 v v v 都有蝴蝶,贡献为 p u ⋅ p v ⋅ s u m u ⋅ ( k − s u m u ) p_u\cdot p_v\cdot sum_u\cdot (k-sum_u) pu​⋅pv​⋅sumu​⋅(k−sumu​)
  • u u u 和 v v v 都没蝴蝶,贡献为 ( 1 − p u ) ⋅ ( 1 − p v ) ⋅ s u m u ⋅ ( k − s u m u ) (1-p_u)\cdot (1-p_v)\cdot sum_u\cdot (k-sum_u) (1−pu​)⋅(1−pv​)⋅sumu​⋅(k−sumu​)
  • u u u 有蝴蝶, v v v 没有蝴蝶,此时有 1 2 \frac 1 2 21​ 的概率蝴蝶从 u u u 飞到 v v v,导致 s u m u sum_u sumu​ 少 1 1 1,贡献为 p u ⋅ ( 1 − p v ) ⋅ s u m u ⋅ ( k − s u m u ) + ( s u m u − 1 ) ( k − s u m u + 1 ) 2 p_u\cdot (1-p_v)\cdot \frac {sum_u\cdot (k-sum_u)+(sum_u-1)(k-sum_u+1)}{2} pu​⋅(1−pv​)⋅2sumu​⋅(k−sumu​)+(sumu​−1)(k−sumu​+1)​
  • u u u 没有蝴蝶, v v v 有蝴蝶,此时有 1 2 \frac 1 2 21​ 的概率蝴蝶从 v v v 飞到 u u u,导致 s u m u sum_u sumu​ 多 1 1 1,贡献为 ( 1 − p u ) ⋅ p v ⋅ s u m u ⋅ ( k − s u m u ) + ( s u m u + 1 ) ( k − s u m u − 1 ) 2 (1-p_u)\cdot p_v\cdot \frac {sum_u\cdot (k-sum_u)+(sum_u+1)(k-sum_u-1)}{2} (1−pu​)⋅pv​⋅2sumu​⋅(k−sumu​)+(sumu​+1)(k−sumu​−1)​

对以上 4 4 4 种情况求和就是边 ( u , v ) (u,v) (u,v) 的贡献。

具体实现的时候可以对 u u u 和 v v v 限定父子关系,这样容易计算。

记得最后要除以 k ( k − 1 ) 2 \frac {k(k-1)}{2} 2k(k−1)​.

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 300005;
const LL mod = 998244353;
int n, k, cnt = 0, fir[N], nxt[N << 1], to[N << 1], fa[N];
LL ans = 0, p[N], s[N];
void ade(int u, int v) {cnt++, nxt[cnt] = fir[u], fir[u] = cnt, to[cnt] = v;cnt++, nxt[cnt] = fir[v], fir[v] = cnt, to[cnt] = u;
}
LL qpow(LL x, LL y) {LL sum = 1;while (y) {if (y & 1) sum = sum * x % mod;x = x * x % mod, y >>= 1;}return sum;
}
void dfs(int r, int f) {fa[r] = f, s[r] = p[r];for (int i = fir[r]; i; i = nxt[i])if (to[i] != f)dfs(to[i], r), s[r] += s[to[i]];
}
int main() {scanf("%d%d", &n, &k);for (int i = 1, x; i <= k; i++) scanf("%d", &x), p[x] = 1;for (int i = 1, u, v; i < n; i++) scanf("%d%d", &u, &v), ade(u, v);dfs(1, 0);LL inv2 = qpow(2, mod - 2);for (int i = 1; i <= cnt; i += 2) {int u = to[i], v = to[i + 1];if (fa[v] != u) swap(u, v);//限定 u 为 v 的父亲ans = ((ans+ p[u] * p[v] % mod * s[v] % mod * (k - s[v]) % mod+ (1 - p[u]) * (1 - p[v]) % mod * s[v] % mod * (k - s[v]) % mod+ (1 - p[u]) * p[v] % mod * (s[v] * (k - s[v]) % mod + (s[v] - 1) * (k - s[v] + 1) % mod) % mod * inv2 % mod+ p[u] * (1 - p[v]) % mod * (s[v] * (k - s[v]) % mod + (s[v] + 1) * (k - s[v] - 1) % mod) % mod * inv2 % mod) % mod + mod) % mod;p[u] = p[v] = (p[u] + p[v]) * inv2 % mod;//概率转移}printf("%lld", (ans * qpow(1ll * k * (k - 1) / 2 % mod, mod - 2) % mod + mod) % mod);return 0;
}

END

【题解】CF1770E Koxia and Tree相关推荐

  1. CF1770E Koxia and Tree

    题目描述 Imi has an undirected tree with n n n vertices where edges are numbered from 1 1 1 to n − 1 n-1 ...

  2. LeetCode题解:Balanced Binary Tree

    Given a binary tree, determine if it is height-balanced. For this problem, a height-balanced binary ...

  3. 题解-hzy loves segment tree I

    Problem 题目概要:给定一棵 \(n\) 个节点的树,点有点权,进行 \(m\) 次路径取\(\max\)的操作,最后统一输出点权 \(n\leq 10^5,m\leq 5\times 10^6 ...

  4. 阔力梯的树(2020 CCPC Wannafly Winter Camp Day2 Div.12 )dsu on tree

    题解: dsu on tree dsu on tree的基本步骤就不说了 看到这题询问结点的子树问题,而且询问时离线的,首先想到的dsu on tree的这个trick. 本题的难题就是如何维护结点所 ...

  5. CF570D Tree Requests(dsu on tree)

    题解: dsu on tree 首先dsu on tree是一个离线的算法,所以我们需要先把他们的询问储存起来,然后进行操作. 针对于每一个结点,我们先统计出他和他子树的所有信息,然后对于这个结点来说 ...

  6. dsu on tree 模板题目(CF600E Lomsat gelral)

    题解: dsu on tree 对于结点i来说,步骤为: 递归轻儿子,不保留贡献. 递归重儿子,保留贡献. 统计当前结点及所有轻儿子的贡献. 拿个样例来解释算法的流程 比如说样例2: 如图所示,有多个 ...

  7. LeetCode 145. Binary Tree Postorder Traversal

    原题链接在这里:https://leetcode.com/problems/binary-tree-postorder-traversal/ 题目: Given a binary tree, retu ...

  8. 由任意二叉树的前序遍历序列和中序遍历序列求二叉树的思想方法_算法与数据结构基础 - 二叉树(Binary Tree)...

    二叉树基础 满足这样性质的树称为二叉树:空树或节点最多有两个子树,称为左子树.右子树, 左右子树节点同样最多有两个子树. 二叉树是递归定义的,因而常用递归/DFS的思想处理二叉树相关问题,例如Leet ...

  9. 2019年12月7日PAT甲级满分题解与经验总结

    PAT2019冬季甲级满分代码+占坑经验分享 考题体验 A题 题目+题解 题目 题解 B题 题目+题解 题目 题解 C题 题目+题解 题目 题解 D题 题目+题解 题目 题解 考场体验,ide经验提高 ...

最新文章

  1. 有 OC 经验的程序员快速学习 Swift 语法
  2. PHP的ob输出缓冲函数作用
  3. 在同一个类中调用另一个方法没有触发 Spring AOP 的问题
  4. MySQL史上最快逻辑备份工具
  5. 【Kettle】job中设置自动发送邮件
  6. web自动化测试第6步:模拟鼠标操作(ActionChains)
  7. android 通过platform.pk8,platform.x509.pem生成jks签名文件
  8. 【安卓】悬浮球源代码(长按判断、多次点击判断、自动贴边)
  9. 有什么软件可以测试游戏视频数据,免费录制游戏视频软件有哪些?看完你就知道了...
  10. VS code 使用技巧-设置鼠标滚轮翻页速度(Mac版本)
  11. 惠普f5静音键指示灯不亮(转载)
  12. 江民KV2007离线包和安装包下载
  13. 点云配准--4PCS原理与应用
  14. 对封装、继承、多态、抽象的理解
  15. 如何把一个qmake的Ubuntu手机应用打包为一个snap应用
  16. [转载] 蝴蝶上如何做种候选及发布
  17. 想知道车牌号码里都有什么秘密吗?
  18. 小米机器人扫地机贴纸_这次小米没吹牛,小米机器人扫地机评测
  19. Python数据采集与处理之网页爬取
  20. “编程思维”到底是一种什么样的思维?

热门文章

  1. MAYA刷权重卡顿问题
  2. Java使用OpenOffice实现文件转换为PDF文件(三)
  3. Word的操作技巧,轻松成为职场高手
  4. 光伏累计装机全国第二 青海光伏全产业链如何炼成?
  5. java入门之基本语句,语法
  6. 自定义View 1-2 Paint.md
  7. sniffer简单使用
  8. 不重启Linux系统重新扫描新增磁盘
  9. 浅尝博弈论(自认为还是比较详细清楚吧)
  10. I.MX6U-系统移植-3-uboot启动流程