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 n1 . The i i i -th edge connects vertices u i u_i ui and v i v_i vi . There are also k k k butterflies on the tree. Initially, the i i i -th butterfly is on vertex a i a_i ai . All values of a a a are pairwise distinct.

Koxia plays a game as follows:

  • For i = 1 , 2 , … , n − 1 i = 1, 2, \dots, n - 1 i=1,2,,n1 , Koxia set the direction of the i i i -th edge as u i → v i u_i \rightarrow v_i uivi or v i → u i v_i \rightarrow u_i viui with equal probability.
  • For i = 1 , 2 , … , n − 1 i = 1, 2, \dots, n - 1 i=1,2,,n1 , if a butterfly is on the initial vertex of i i i -th edge and there is no butterfly on the terminal vertex, then this butterfly flies to the terminal vertex. Note that operations are sequentially in order of 1 , 2 , … , n − 1 1, 2, \dots, n - 1 1,2,,n1 instead of simultaneously.
  • Koxia chooses two butterflies from the k k k butterflies with equal probability from all possible k ( k − 1 ) 2 \frac{k(k-1)}{2} 2k(k1) ways to select two butterflies, then she takes the distance † ^\dagger between the two chosen vertices as her score.

Now, Koxia wants you to find the expected value of her score, modulo 998   244   35 3 ‡ 998\,244\,353^\ddagger 998244353 .

† ^\dagger The distance between two vertices on a tree is the number of edges on the (unique) simple path between them.

‡ ^\ddagger Formally, let M = 998   244   353 M = 998\,244\,353 M=998244353 . It can be shown that the answer can be expressed as an irreducible fraction p q \frac{p}{q} qp , where p p p and q q q are integers and q ≢ 0 ( m o d M ) q \not \equiv 0 \pmod{M} q0(modM) . Output the integer equal to p ⋅ q − 1   m o d   M p \cdot q^{-1} \bmod M pq1modM . In other words, output such an integer x x x that 0 ≤ x < M 0 \le x < M 0x<M and x ⋅ q ≡ p ( m o d M ) x \cdot q \equiv p \pmod{M} xqp(modM) .

题意简述

一棵有 n n n 个节点的树,其中有 k k k 个节点上有一只蝴蝶。

  • 你可以选择对每一条边随机的指定一个方向。
  • 按照编号顺序依次选择每一条边,如果起点有蝴蝶,终点没有蝴蝶,则蝴蝶从起点飞到终点。
  • 随机的选择两只蝴蝶,求他们距离的期望值。距离是两点之间的边数。

题解

如果不考虑蝴蝶的移动,这就是一个经典问题:求 k k k 个蝴蝶两两距离的期望。

对于这个问题,可以枚举每条边,这条边把整棵树分成两份,若左边的点要走到右边的点去,则一定会经过这条边,对答案的贡献就是两边蝴蝶个数的乘积。最后再除上 k ( k − 1 ) 2 \frac{k(k-1)}2 2k(k1) 就是最终的答案。

现在考虑蝴蝶的移动。再次枚举每条边,此时蝴蝶移动的可能性有三种:

  • 蝴蝶在左边,且移动后的位置也在左边
  • 蝴蝶在右边,且移动后的位置也在右边
  • 蝴蝶在枚举的边的端点上

可以看到无论如何,左右两边的蝴蝶数量最多变化 1 1 1,且只有蝴蝶在枚举的边的端点上时才可能变化。

由于蝴蝶移动是概率性的,不妨设节点 u u u 有蝴蝶的概率为 p u p_u pu,再设 s u s_u su 为子树 u u u 中蝴蝶的数量。

按照编号由小到大枚举每条边 ( u , v ) (u,v) (u,v),其中 v v v u u u 的父亲,考虑求出这条边的贡献,分情况讨论:

  • u u u v v v 都有蝴蝶,此时的贡献为 p u ⋅ p v ⋅ s u ⋅ ( k − s u ) p_u\cdot p_v\cdot s_u\cdot(k-s_u) pupvsu(ksu)
  • u u u v v v 都没有蝴蝶,此时的贡献为 ( 1 − p u ) ⋅ ( 1 − p v ) ⋅ s u ⋅ ( k − s u ) (1-p_u)\cdot(1-p_v)\cdot s_u\cdot(k-s_u) (1pu)(1pv)su(ksu)
  • u u u 有蝴蝶, v v v 没有蝴蝶,此时有 1 2 \frac12 21 的概率蝴蝶会从 u u u 飞到 v v v,贡献为 p u ⋅ ( 1 − p v ) ⋅ s u ⋅ ( k − s u ) + ( s u − 1 ) ⋅ ( k − s u + 1 ) 2 p_u\cdot(1-p_v)\cdot\frac{s_u\cdot(k-s_u)+(s_u-1)\cdot(k-s_u+1)}{2} pu(1pv)2su(ksu)+(su1)(ksu+1)
  • u u u 没有蝴蝶, v v v 有蝴蝶,此时有 1 2 \frac12 21 的概率蝴蝶会从 v v v 飞到 u u u,贡献为 ( 1 − p u ) ⋅ p v ⋅ s u ⋅ ( k − s u ) + ( s u + 1 ) ⋅ ( k − s u − 1 ) 2 (1-p_u)\cdot p_v\cdot\frac{s_u\cdot(k-s_u)+(s_u+1)\cdot(k-s_u-1)}{2} (1pu)pv2su(ksu)+(su+1)(ksu1)

把以上贡献加起来就是边 ( u , v ) (u,v) (u,v) 的贡献。

蝴蝶在边 ( u , v ) (u,v) (u,v) 上有概率移动, p u p_u pu 也会变化,考虑分四种情况讨论如何转移 p u p_u pu

  • u u u v v v 都有蝴蝶,显然概率为 p u ⋅ p v p_u\cdot p_v pupv
  • u u u v v v 都没有蝴蝶,显然概率为 0 0 0
  • u u u 有蝴蝶, v v v 没有蝴蝶,有 1 2 \frac12 21 的概率蝴蝶不会从 u u u 飞到 v v v,因此概率为 p u ⋅ ( 1 − p v ) 2 \frac{p_u\cdot(1-p_v)}{2} 2pu(1pv)
  • u u u 没有蝴蝶, v v v 有蝴蝶,有 1 2 \frac12 21 的概率蝴蝶会从 v v v 飞到 u u u,因此概率为 ( 1 − p u ) ⋅ p v 2 \frac{(1-p_u)\cdot p_v}{2} 2(1pu)pv

总的概率为 p u ⋅ p v + p u ⋅ ( 1 − p v ) 2 + ( 1 − p u ) ⋅ p v 2 = p u + p v 2 p_u\cdot p_v+\frac{p_u\cdot(1-p_v)}{2}+\frac{(1-p_u)\cdot p_v}{2}=\frac{p_u+p_v}{2} pupv+2pu(1pv)+2(1pu)pv=2pu+pv

即转移时 p u ← p u + p v 2 p_u\gets \frac{p_u+p_v}{2} pu2pu+pv

对于 p v p_v pv 同理,也为 p u + p v 2 \frac{p_u+p_v}{2} 2pu+pv,和 p u p_u pu 相等。

别忘记最后答案要除以 k ( k − 1 ) 2 \frac{k(k-1)}{2} 2k(k1)

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=998244353;
const int N=3e5+1;
int n,k;
int head[N],nxt[N<<1],to[N<<1],cnt,fa[N];
ll t[N],ans,p[N],s[N];
ll ksm(ll a,ll b)
{
    ll ans=1;
    while(b){
        if(b&1) ans=ans*a%mod;
        b>>=1;
        a=a*a%mod;
    }
    return ans;
}
void add(int u,int v)
{
    to[++cnt]=v;
    nxt[cnt]=head[u];
    head[u]=cnt;
}
void dfs(int u,int f)
{
    fa[u]=f;
    s[u]=p[u];
    for(int i=head[u];i;i=nxt[i]){
        if(to[i]!=f){
            dfs(to[i],u);
            s[u]+=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);
        add(u,v),add(v,u);
    }
    dfs(1,0);
    ll inv2=ksm(2,mod-2);
    for(int i=1;i<=cnt;i+=2){
        int u=to[i],f=to[i+1];
        if(fa[u]!=f) swap(u,f);
        ans=((ans
        +p[u]*p[f]%mod*(k-s[u])%mod*s[u]%mod
        +(1-p[u])*(1-p[f])%mod*(k-s[u])%mod*s[u]%mod
        +p[u]*(1-p[f])%mod*((k-s[u])*s[u]%mod+(k-s[u]+1)*(s[u]-1)%mod)%mod*inv2%mod
        +(1-p[u])*p[f]%mod*((k-s[u])*s[u]%mod+(k-s[u]-1)*(s[u]+1)%mod)%mod*inv2%mod
        )%mod+mod)%mod;
        p[u]=p[f]=(p[u]+p[f])*inv2%mod;
    }
    cout<<ans*ksm(1ll*k*(k-1)/2%mod,mod-2)%mod;
}
  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值