• Solution -「Gym 102979E」Expected Distance


    (mathcal{Description})

      Link.

      用给定的 ({a_{n-1}},{c_n}) 生成一棵含有 (n) 个点的树,其中 (u) 连向 ([1,u)) 中的某个 (v),概率为 (frac{a_v}{a_1+a_2+cdots+a_{u-1}}),边权为 (c_u+c_v)。并给出 (q) 组询问 ((u_i,v_i)),每次回答 (u_i)(v_i) 的树上距离的期望。答案对 ((10^9+7)) 取模。

      (n,qle3 imes10^5)

    (mathcal{Solution})

    [ extit{Defining }LaTeX extit{ macros...} ewcommand{vct}[1]{oldsymbol{#1}} ewcommand{stir}[2]{genfrac{{}{}}{0pt}{}{#1}{#2}} ewcommand{opn}[1]{operatorname{#1}} ewcommand{lcm}[0]{opn{lcm}} ewcommand{sg}[0]{opn{sg}} ewcommand{dist}[0]{opn{dist}} ewcommand{lca}[0]{opn{lca}} ewcommand{floor}[2]{leftlfloorfrac{#1}{#2} ight floor} ewcommand{ceil}[2]{leftlceilfrac{#1}{#2} ight ceil} ]

      问题卡壳,必有结论。

      令 (1) 为根,把 (dist(u,v)) 转化成 (dist(1,u)+dist(1,v)-2dist(lca(u,v)))。记 (f(u)=E(dist(1,u))),显然有

    [f(u)=c_u+frac{1}{s_{u-1}}sum_{v<u}a_v(f_v+c_v). ]

    其中 (s_i=sum_{j=1}^ia_i),可见 (f) 可以轻易地 (mathcal O(n)) 求出。我们接下来研究 (dist(lca(u,v)))。不妨设 (u<v),可以发现一个结论:

    [forall v>u,~E(dist(lca(u,v)))=g(u). ]

    其中 (g(u)) 是仅与 (u) 有关的量。

    证明   考虑求 $lca(u,v)$ 的方式,在 $v$ 沿着祖先跳跃时,我们只关心第一次使得 $vle u$ 的位置。此时仅有两种情况
    • (v=u),概率为 (frac{a_u}{s_u})
    • (v<u),概率为 (frac{s_{u-1}}{s_u})

      可见与 (v) 无关。

      在证明的基础上,亦能得到 (g(u)) 的转移:

    [g(u)=frac{1}{s_u}left(a_uc_u+sum_{v<u}a_vg_v ight). ]

    也能 (mathcal O(n)) 求出,所以本题就解决啦。

    (mathcal{Code})

    /*~Rainybunny~*/
    
    #include <bits/stdc++.h>
    
    #define rep( i, l, r ) for ( int i = l, rep##i = r; i <= rep##i; ++i )
    #define per( i, r, l ) for ( int i = r, per##i = l; i >= per##i; --i )
    
    const int MAXN = 3e5, MOD = 1e9 + 7;
    int n, q, a[MAXN + 5], s[MAXN + 5], invs[MAXN + 5];
    int c[MAXN + 5], f[MAXN + 5], g[MAXN + 5];
    
    inline int mul( const int a, const int b ) { return 1ll * a * b % MOD; }
    inline int sub( int a, const int b ) { return ( a -= b ) < 0 ? a + MOD : a; }
    inline int add( int a, const int b ) { return ( a += b ) < MOD ? a : a - MOD; }
    inline int mpow( int a, int b ) {
        int ret = 1;
        for ( ; b; a = mul( a, a ), b >>= 1 ) ret = mul( ret, b & 1 ? a : 1 );
        return ret;
    }
    
    int main() {
        std::ios::sync_with_stdio( false ), std::cin.tie( 0 );
    
        std::cin >> n >> q;
        rep ( i, 1, n - 1 ) {
            std::cin >> a[i], s[i] = a[i] + s[i - 1];
            invs[i] = mpow( s[i], MOD - 2 );
        }
        rep ( i, 1, n ) std::cin >> c[i];
    
        for ( int i = 2, pre = mul( a[1], c[1] ); i <= n; ++i ) {
            f[i] = add( c[i], mul( invs[i - 1], pre ) );
            pre = add( pre, mul( a[i], add( f[i], c[i] ) ) );
        }
    
        for ( int i = 2, pre = 0; i < n; ++i ) {
            g[i] = mul( invs[i], add( mul( a[i], f[i] ), pre ) );
            pre = add( pre, mul( a[i], g[i] ) );
        }
    
        for ( int u, v; q--; ) {
            std::cin >> u >> v;
            if ( u > v ) u ^= v ^= u ^= v;
            if ( u == v ) std::cout << "0
    ";
            else std::cout << sub( add( f[u], f[v] ), mul( 2, g[u] ) ) << '
    ';
        }
        return 0;
    }
    
    
  • 相关阅读:
    号称简明实用的django上手教程
    转先验概率、最大似然估计、贝叶斯估计、最大后验概率
    转基于概率的矩阵分解原理详解(PMF)
    转浅谈矩阵分解在推荐系统中的应用
    转推荐算法——基于矩阵分解的推荐算法
    代码生成器的需求
    兼容性的设计要求
    API设计的需求
    有关表单的需求梳理
    element-ui table 点击分页table滚到顶部
  • 原文地址:https://www.cnblogs.com/rainybunny/p/15203297.html
Copyright © 2020-2023  润新知