(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;
}