P10227 [COCI 2023/2024 #3] Slučajna Cesta 题解
知识点
期望 DP,树形(换根) DP,组合数学。
题意分析
一棵树,每个点都有点权,每一条边的方向分布都是等概率的,问从每个点出发,有路走就一直走的情况下,所途径的点的权值总和的期望值。
思路分析
这明显是一个树形 DP,且需要变成换根 DP 才能过得了这题。
先考虑最基础的树形 DP 暴力:那么设 \(f_u\) 表示从点 \(u\) 开始往子节点走,满足有路走就一直走的情况下,所途径的点的权值总和的期望值。
设一个点 \(u\) 有 \(d_u\) 个子节点,那么我们就可以分情况讨论:
对于通向子节点的边能不能走,共有 \(2^{d_u}\) 种情况。
再根据期望的线性性质,计算每个子节点的 DP 值 \(f_v\) 对 \(f_u\) 的贡献,就是下面这个式子:
\[f_v \cdot \frac{\sum_{i=0}^{d_u-1}\frac{\begin{pmatrix}d_u-1\\i\end{pmatrix}}{i+1}}{2^{d_u}} \]解释一下:\(\frac{\sum_{i=0}^{d_u-1}\frac{\begin{pmatrix}d_u-1\\i\end{pmatrix}}{i+1}}{2^{d_u}}\) 表示从 \(u\) 走到 \(v\) 的概率。其中作为分母的 \(\frac{1}{2^{d_u}}\) 表示总情况数,上面每次枚举的 \(i\) 表示在 \(u\) 能够通向 \(v\) 时,还能通向几个子节点,那么单次去到 \(v\) 的概率就是 \(\frac{1}{i+1}\),这种情况的数量就是 \(\begin{pmatrix}d_u-1\\i\end{pmatrix}\),乘起来就是概率。
那么 \(f_u\) 的值就是:
\[v_u + \frac{\sum_{i=0}^{d_u-1}\frac{\begin{pmatrix}d_u-1\\i\end{pmatrix}}{i+1}}{2^{d_u}} \cdot \sum_{(u,v) \in G} f_v \]那么我们已经可以拿到 Subtask 1 的分了 (卡一卡 Subtask 2 也是轻轻松松)。
但这明显不够,我们力求完美。这个一看就可以化简 (二项式定理随便搞搞),我们这里讲两种方法。
两种方法都得先化到一定程度:发现概率中有一个会变的分母 \(i+1\),尝试把它转成一个常量。(只化简能化的概率部分)
\[\begin{aligned} & \frac{\sum_{i=0}^{d_u-1}\frac{\begin{pmatrix}d_u-1\\i\end{pmatrix}}{i+1}}{2^{d_u}} \\ & = \frac{\sum_{i=0}^{d_u-1}\frac{(d_u-1)!}{(i+1) \cdot i! \cdot (d_u - i - 1)}}{2^{d_u}} \\ & = \frac{\sum_{i=0}^{d_u-1}\frac{(d_u-1)!}{(i+1)! \cdot (d_u - i - 1)}}{2^{d_u}} \\ & = \frac{\sum_{i=1}^{d_u}\begin{pmatrix}d_u\\i\end{pmatrix}}{d_u \cdot 2^{d_u}} \\ \end{aligned} \]-
二项式定理:
好了,到这里,一般数学好的同学已经发现上面的 \(\sum_{i=1}^{d_u}\begin{pmatrix}d_u\\i\end{pmatrix}\) 可以用二项式定理了,那我们就先推一下他:
\[\begin{aligned} & \prod_{i=1}^n (1+a_ix) \\ & = 1 + (\sum_{i=1}^n a_i) \cdot x + (\sum_{i=1}^n \sum_{j=i+1}^n a_i a_j) x^2 + \cdots + (\prod_{i=1}^n a_i) x^n \\ \end{aligned} \]在这里只用在题目里的话,设 \(a_i = 1,\forall i\in[1,n]\),式子变为:
\[\begin{aligned} \prod_{i=1}^n (1+a_ix) & = 1 + (\sum_{i=1}^n a_i) \cdot x + (\sum_{i=1}^n \sum_{j=i+1}^n a_i a_j) x^2 + \cdots + (\prod_{i=1}^n a_i) x^n \\ (1+x)^n & = 1 + \begin{pmatrix} n \\ 1 \end{pmatrix} x + \begin{pmatrix} n \\ 2 \end{pmatrix} x^2 + \cdots +\begin{pmatrix} n \\ n \end{pmatrix} x^n \\ (1+x)^n & = \sum_{i=0}^n \begin{pmatrix} n \\ i \end{pmatrix} x^i \end{aligned} \]这个时候,再设 \(x=1\),式子就变成了我们想要的样子:
\[\begin{aligned} (1+x)^n & = \sum_{i=0}^n \begin{pmatrix} n \\ i \end{pmatrix} x^i \\ (1+1)^n & = \sum_{i=0}^n \begin{pmatrix} n \\ i \end{pmatrix} 1^i \\ 2^n & = \sum_{i=0}^n \begin{pmatrix} n \\ i \end{pmatrix} \\ \end{aligned} \]于是,我们上面的概率就变成了:
\[\begin{aligned} & \frac{\sum_{i=1}^{d_u}\begin{pmatrix}d_u\\i\end{pmatrix}}{d_u \cdot 2^{d_u}} \\ & = \frac{2^{d_u}-1}{d_u \cdot 2^{d_u}} \\ \end{aligned} \] -
手推递推式:
想不到上面这种方法的同学也不要气馁,车到山前必有路,我们再想想。如果实在想不出来,可以试试先做一下这题,我就是受这题莫队方法的启发(不会莫队的同学不必慌张,跟这题没关系)。
设 \(f_{x,y} = \sum_{i=1}^{x}\begin{pmatrix} y \\ i \end{pmatrix}\)。但是它少一个 \(\begin{pmatrix} y \\ 0 \end{pmatrix}\),不好处理,那么我们把它加上:设 \(g_{x,y} = \sum_{i=0}^{x}\begin{pmatrix} y \\ i \end{pmatrix}\),那么显而易见,\(f_{x,y} = g_{x,y} - 1\)。
我们发现,从 \(g_{x,y}\) 其实可以推出 \(g_{x,y+1}\) 与 \(g_{x+1,y}\):
-
\(g_{x,y} \to g_{x,y+1}\):
\[\begin{aligned} g_{x,y+1} & = \sum_{i=0}^{x}\begin{pmatrix} y+1 \\ i \end{pmatrix} \\ g_{x,y+1} & = \sum_{i=0}^{x}[\begin{pmatrix} y \\ i \end{pmatrix}+\begin{pmatrix} y \\ i-1 \end{pmatrix}] \\ g_{x,y+1} & = \sum_{i=0}^{x}\begin{pmatrix} y \\ i \end{pmatrix}+ \sum_{i=0}^{x-1} \begin{pmatrix} y \\ i \end{pmatrix} \\ g_{x,y+1} & = 2 g_{x,y} - \begin{pmatrix} y \\ x \end{pmatrix} \\ \end{aligned} \] -
\(g_{x,y} \to g_{x+1,y}\):
\[\begin{aligned} g_{x+1,y} & = \sum_{i=0}^{x+1}\begin{pmatrix} y \\ i \end{pmatrix} \\ g_{x+1,y} & = \sum_{i=0}^{x}\begin{pmatrix} y \\ i \end{pmatrix} + \begin{pmatrix} y \\ x+1 \end{pmatrix}\\ g_{x+1,y} & = g_{x,y} + \begin{pmatrix} y \\ x+1 \end{pmatrix}\\ \end{aligned} \]
那么从 \(g_{x,x}\) 就可以推到 \(g_{x+1,x+1}\):
\[\begin{aligned} g_{x,x+1} & = 2 g_{x,x} - \begin{pmatrix} x \\ x \end{pmatrix} \\ g_{x+1,x+1} & = g_{x,x+1} + \begin{pmatrix} x+1 \\ x+1 \end{pmatrix} \\ g_{x+1,x+1} & = 2 g_{x,x}\\ \end{aligned} \]那么 \(g_{x,x} = 2^x \cdot g_{0,0},g_{0,0}=1\),即 \(g_{x,x}=2^x,f_{x,x}=2^x-1\)。
同样也能得出概率为:
\[\begin{aligned} & \frac{\sum_{i=1}^{d_u}\begin{pmatrix}d_u\\i\end{pmatrix}}{d_u \cdot 2^{d_u}} \\ & = \frac{2^{d_u}-1}{d_u \cdot 2^{d_u}} \\ \end{aligned} \] -
总结一下上面的推导过程,得到结论:
\[\begin{aligned} f_u & = v_u + \frac{\sum_{i=0}^{d_u-1}\frac{\begin{pmatrix}d_u-1\\i\end{pmatrix}}{i+1}}{2^{d_u}} \cdot \sum_{(u,v) \in G} f_v \\ f_u & = v_u + \frac{2^{d_u}-1}{d_u \cdot 2^{d_u}} \cdot \sum_{(u,v) \in G} f_v \\ \end{aligned} \]然后在树形 DP 的基础上再推出换根 DP 就可以拿到满分了!(ヾ(@▽@)ノ欢呼)
时间复杂度在不预处理的情况下是 \(O(n\log_2{P})\) 的,其中 \(P = 10^9 + 7\),\(\log_2{P}\) 是处理逆元的时间复杂度,但是发现我们所有的逆元都可以 \(O(n)\) 预处理,然后一些其他地方转化一下,就可以去掉这个 \(\log_2{P}\) 了!
CODE
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define ll long long
#define max(a,b) ((a)<(b)?(b):(a))
#define min(a,b) ((a)>(b)?(b):(a))
#define tomax(a,b) ((a)=max((a),(b)))
#define tomin(a,b) ((a)=min((a),(b)))
#define RCL(a,b,c,d) memset((a),(b),sizeof(c)*(d))
#define FOR(i,a,b) for(register int i=(a);i<=(b);++i)
#define DOR(i,a,b) for(register int i=(a);i>=(b);--i)
#define EDGE(g,i,u,x) for(register int (i)=(g).h[(u)],(x)=(g).v[(i)];(i);(i)=(g).nxt[(i)],(x)=(g).v[(i)])
#define main Main();signed main(){ios::sync_with_stdio(0);cin.tie(0);return Main();}signed Main
using namespace std;
constexpr int N=1e6+10;
namespace Modular_Arithmetic{
#define MOD 1000000007
#define toadd(a,b) ((a)=add((a),(b)))
#define tomul(a,b) ((a)=mul((a),(b)))
int pw[N],pinv[N],Inv[N],val[N];
template<typename T1,typename T2>constexpr auto add(T1 a,T2 b){
return a+b>=MOD?a+b-MOD:a+b<0?a+b+MOD:a+b;
}
template<typename T1,typename T2>constexpr auto mul(T1 a,T2 b){
return (long long)a*b%MOD;
}
template<typename T,typename...Types>constexpr auto add(T a,Types... b){
return add(a,add(b...));
}
template<typename T,typename...Types>constexpr auto mul(T a,Types... b){
return mul(a,mul(b...));
}
int Pow(int a,int b){
int res=1;
for(a%=MOD;b;b>>=1,tomul(a,a))if(b&1)tomul(res,a);
return res;
}
void Init(int n){
pw[0]=1;
FOR(i,1,n)pw[i]=mul(pw[i-1],2);
pinv[n]=Pow(pw[n],MOD-2);
DOR(i,n,1)pinv[i-1]=mul(pinv[i],2);
Inv[0]=Inv[1]=1;
FOR(i,2,n)Inv[i]=1ll*(MOD-MOD/i)*Inv[MOD%i]%MOD;
FOR(i,0,n)val[i]=mul(add(pw[i],-1),Inv[i],pinv[i]);
}
}using namespace Modular_Arithmetic;
int n;
int a[N],d[N],f[N],h[N];
struct CFS{
int tot,h[N],v[N<<1],nxt[N<<1];
void att(int U,int V){
v[++tot]=V,nxt[tot]=h[U],h[U]=tot;
}
void con(int U,int V){
att(U,V),att(V,U);
}
}g;
void dfs0(int u,int fa){
d[u]=0,f[u]=0,h[u]=0;
EDGE(g,i,u,v)if(v^fa)++d[u],dfs0(v,u),toadd(h[u],f[v]);
f[u]=add(a[u],mul(h[u],val[d[u]]));
}
void dfs1(int u,int fa){
if(u>1)++d[u];
f[u]=add(a[u],mul(h[u],val[d[u]]));
EDGE(g,i,u,v)if(v^fa)toadd(h[v],add(a[u],mul(add(h[u],-f[v]),val[d[u]-1]))),dfs1(v,u);
}
signed main(){
rd(n),Init(n);
FOR(i,2,n){
int x;
rd(x),g.con(x,i);
}
FOR(i,1,n)rd(a[i]);
dfs0(1,0),dfs1(1,0);
FOR(i,1,n)wr(f[i]);
return 0;
}
提示:把取模运算封装一下会方便很多哦。
标签:begin,end,P10227,题解,sum,pmatrix,Slu,frac,aligned From: https://www.cnblogs.com/Cat-litter/p/18188153