当前位置: 首页 > article >正文

CF1770E Koxia and Tree

CF1770E Koxia and Tree

题目大意

有一棵 n n n个结点的无根树,边从 1 1 1 n − 1 n-1 n1标号,第 i i i条边连接结点 u i u_i ui v i v_i vi

k k k个结点带有标记,分别是 a 1 , a 2 , … a k ( ∀ i ≠ j , a i ≠ a j ) a_1,a_2,\dots a_k(\forall i\neq j,a_i\neq a_j) a1,a2,ak(i=j,ai=aj)。接下来,进行如下操作:

  • 给每条边随机定一个方向
  • 按照编号的顺序,对于每条边 u → v u\rightarrow v uv,如果结点 u u u有标记而结点 v v v没有,那么就把结点 u u u的标记转移到结点 v v v
  • 随机选取两个不同的标记点,计算它们的距离。

请你计算第三步中距离的期望值。对 998244353 998244353 998244353取模。


题解

我们先考虑如果不转移标记,距离的期望值为多少。

此时距离的期望值就是任意两点距离的总和减去任意选择两个点的方案数,那么只需求出任意两点距离的总和即可。我们可以分别计算每条边的贡献。因为路径上有这条边的两个点一定是一个在左一个在右,所以一条边的贡献为其左边的结点中有标记的点的个数与右边的结点中有标记的点的个数之积。令一个点为根,维护每个结点所在子树的有标记的点的个数,即可用dfs来 O ( n ) O(n) O(n)求出答案。

在这里插入图片描述
我们再考虑会转移标记的情况下的距离期望值。

首先我们知道,在遍历一条边之前,没有标记能跨越这条边,所以这条边两边的有标记的点是不变的。对于一条边 ( u , v ) (u,v) (u,v),假设 u u u v v v的父亲,那么 u u u这边有标记的点的个数为 k − s v k-s_v ksv v v v这边有标记的点的个数 s v s_v sv

u u u点有标记的概率为 f u f_u fu v v v点有标记的概率为 f v f_v fv。我们可以分类讨论。

  • 两端都有点,则贡献为 f u × f v × ( k − s v ) × s v f_u\times f_v\times (k-s_v)\times s_v fu×fv×(ksv)×sv
  • u u u有点, v v v没有点,如果方向为 u → v u\rightarrow v uv,则 u u u点的标记转移到 v v v,否则不转移,概率各占 1 2 \dfrac 12 21,贡献为
    ( 1 − f u ) × f v × ( k − s v − 1 ) × ( s v + 1 ) + ( k − s v ) × s v 2 \qquad \qquad (1-f_u)\times f_v\times\dfrac{(k-s_v-1)\times (s_v+1)+(k-s_v)\times s_v}{2} (1fu)×fv×2(ksv1)×(sv+1)+(ksv)×sv
  • u u u没有点, v v v有点,如果方向为 v → u v\rightarrow u vu,则 v v v点的标记转移到 u u u,否则不转移,概率各占 1 2 \dfrac 12 21,贡献为
    f u × ( 1 − f v ) × ( k − s v + 1 ) × ( s v − 1 ) + ( k − s v ) × s v 2 \qquad \qquad f_u\times (1-f_v)\times\dfrac{(k-s_v+1)\times (s_v-1)+(k-s_v)\times s_v}{2} fu×(1fv)×2(ksv+1)×(sv1)+(ksv)×sv
  • 两端都没有点,贡献为 ( 1 − f u ) × ( 1 − f v ) × ( k − s v ) × s v (1-f_u)\times (1-f_v)\times (k-s_v)\times s_v (1fu)×(1fv)×(ksv)×sv

这四个式子之和就是这条边对答案的贡献,累加即可。

那么遍历这条边后,两边有点的概率会变为多少呢?

  • 两边都有点,遍历这条边后 u u u有点和 v v v有点的概率为 f u × f v f_u\times f_v fu×fv
  • u u u有点, v v v没有点,遍历这条边后,两种方向的概率各占 1 2 \dfrac 12 21 u u u有点和 v v v有点的概率为 f u × ( 1 − f v ) 2 \dfrac{f_u\times (1-f_v)}{2} 2fu×(1fv)
  • v v v有点, u u u没有点,遍历这条边后,两种方向的概率各占 1 2 \dfrac 12 21 u u u有点和 v v v有点的概率为 ( 1 − f u ) × f v 2 \dfrac{(1-f_u)\times f_v}{2} 2(1fu)×fv
  • 两边没有点,遍历这条边后 u u u有点和 v v v有点的概率为 ( 1 − f u ) × ( 1 − f v ) (1-f_u)\times (1-f_v) (1fu)×(1fv)

那么遍历这条边后 f u = f v = f u + f v 2 f_u=f_v=\dfrac{f_u+f_v}{2} fu=fv=2fu+fv

最后的答案要乘上方案数的逆元。

时间复杂度为 O ( n ) O(n) O(n)

code

#include<bits/stdc++.h>
using namespace std;
int n,x,y,tot=1,fa[300005],d[600005],l[600005],r[600005];
long long k,ans=0,siz[300005],p[300005];
long long ny2=499122177,mod=998244353;
void add(int xx,int yy){
	l[++tot]=r[xx];d[tot]=yy;r[xx]=tot;
}
void dfs(int u,int f){
	fa[u]=f;siz[u]=p[u];
	for(int i=r[u];i;i=l[i]){
		if(d[i]==f) continue;
		dfs(d[i],u);
		siz[u]+=siz[d[i]];
	}
}
long long mi(long long t,long long v){
	if(!v) return 1;
	long long re=mi(t,v/2);
	re=re*re%mod;
	if(v&1) re=re*t%mod;
	return re;
}
int main()
{
	scanf("%d%lld",&n,&k);
	for(int i=1;i<=k;i++){
		scanf("%d",&x);p[x]=1;
	}
	for(int i=1;i<n;i++){
		scanf("%d%d",&x,&y);
		add(x,y);add(y,x);
	}
	dfs(1,0);
	for(int i=2;i<=tot;i+=2){
		int u=d[i^1],v=d[i];
		if(fa[u]==v) swap(u,v);
		ans=(ans+p[u]*p[v]%mod*(k-siz[v])%mod*siz[v]%mod
			+(mod+1-p[u])*(mod+1-p[v])%mod*(k-siz[v])%mod*siz[v]%mod
			+p[u]*(mod+1-p[v])%mod*((k-siz[v])*siz[v]%mod+(k-siz[v]-1)*(siz[v]+1)%mod)%mod*ny2%mod
			+(mod+1-p[u])*p[v]%mod*((k-siz[v])*siz[v]%mod+(k-siz[v]+1)*(siz[v]-1)%mod)%mod*ny2%mod)%mod;
		p[u]=p[v]=(p[u]+p[v])*ny2%mod;
	}
	printf("%lld",ans*mi(k*(k-1)/2%mod,mod-2)%mod);
	return 0;
}

http://www.kler.cn/a/1872.html

相关文章:

  • 小程序租赁系统开发指南与实现策略
  • 预览和下载 (pc和微信小程序)
  • web-密码安全口令
  • GIS 文件格式 及 常规应用总结
  • 观察者模式(sigslot in C++)
  • HTTP、HTTPS和SOCKS5代理協議
  • 探索css渐变-实现饼图-加载图-灯柱
  • 【Java】UDP网络编程
  • 蓝桥杯算法全集之完全背包问题(动态规划算法)
  • 蓝桥杯真题——自动售水机
  • LeetCode:704. 二分查找
  • 区块链基本原理
  • 【jvm】JVM(三)JVM 垃圾回收算法详解(CMS、三色标记)
  • 【进阶数据结构】二叉搜索树经典习题讲解
  • Python读写EXCEL文件常用方法大全
  • ChatGPT加强版GPT-4面世,打工人的方式将被颠覆
  • 遗传算法原理及案例解析
  • SAP BPC简介
  • vue大型商城系统中遇到的问题(上)
  • 【链表OJ题(九)】环形链表延伸问题以及相关OJ题
  • 5. QtDesignStudio中的3D场景
  • 硬件原理图设计规范(二)
  • 搞懂vue 的 render 函数, 并使用
  • 关于element-plus按需引入时,在vite中使用自定义主题失效的问题解决
  • 【C++学习】类和对象(中)一招带你彻底了解六大默认成员函数
  • 【剧前爆米花--爪哇岛寻宝】java--线程不安全的原因及解决方法