loading

P11736 [集训队互测 2015] 胡策的小树

题意

给定一棵 \(n\) 个点的树,保证 \(i\) 的父亲在 \(1\sim i-1\) 中随机。

初始每个节点上有一枚棋子,每一时刻开始,\(sum\) 为 0。对于每个棋子,设其所在位置为 \(i\),有 \(p_i=\frac{a_i}{n}\) 的概率向父亲走,并使 \(sum\) 加 1;或者等概率的跳到 \(i\) 子树内的点。特殊的,\(p_1\) 恒为 \(0\)。保证 \(a_i\)\(0\sim n-1\) 的排列。

现在要进行这些操作 \(T=(n+1)^{99999^{99999^{99999}}}\) 个时刻,设 \(ans\) 为每个时刻 \(sum\) 值的平均数的平均数的期望,即:\(ans=E\left(\dfrac{\sum_{i=0}^T\frac{sum_i}{n}}{T}\right)\)

你现在可以进行一次操作:\(\forall i,a_i\leftarrow (a_i+x)\bmod n\)。求 \(ans\) 最大值。

\(n\le 5\times10^5\)

分析

考虑 \(x=0\) 的情况,即不进行操作。

\(f_i\) 为某一时刻 \(i\) 点上的猴子个数平均数的期望(即猴子个数期望除以 \(n\) 的值)。可以证明,当 \(T\) 足够大时,\(f_i\) 最终稳定在一个定值上,且 \(f_i\) 不稳定时对答案的贡献可以忽略,所以我们可以直接把答案写成 \(\sum f_i p_i\) 的形式。

考虑怎么求 \(f_i\),显然有递推式 \(f_x=\sum_{u\in son(x)} f_up_u+\sum_{u\in anc(x)}f_u(1-p_u)\frac{1}{siz_u}\)。直接高消复杂度 \(O(n^3)\),不能通过。

考虑树上高消,那么我们就需要求出 \(f_i\)\(f_{fa}\) 的等量关系了(一般情况下 \(f_u=kf_{fa}+b\))。有式子

\[\sum_{u\in subtree(x)} f_u=\sum_{u\in subtree,u\neq x}f_u+\sum_{u\in anc(x)}f_u(1-p_u)\frac{siz_x}{siz_u} \]

两边同时减去 \(\sum_{u\in subtree(x),u\neq x}f_u\)

\[f_x=\sum_{u\in anc(x)}f_u(1-p_u)\frac{siz_x}{siz_u}=f_x(1-p_x)+\frac{siz_x}{siz_{fa}}\sum_{u\in anc(x),u\neq x}f_u(1-p_u)\frac{siz_{fa}}{siz_u} \]

而不难发现 \(\sum_{u\in anc(x),u\neq x}f_u(1-p_u)\frac{siz_{fa}}{siz_u}=f_{fa}\),代入并移项得:

\[p_xf_x=\frac{siz_x}{siz_{fa}}f_{fa} \]

这样就得出了 \(f_x\)\(f_{fa}\) 的等量关系,dfs 一遍就可以求出所有 \(f_i\)\(f_1\) 的等量关系,然后由于一共有 \(n\) 只猴子,所以 \(\sum_i f_i=1\),据此可以求解出 \(f_1\) 的值,继而得出 \(f_i\) 的值。时间复杂度 \(O(n)\)

考虑 \(x\neq 0\) 的情况。此时必定存在一个 \(a_i=0\) 的点,那么对于该点子树以外的棋子,一旦棋子掉落到 \(i\) 子树内就再也出不来了。而在 \(T\) 足够大时,最终所有棋子都会落在 \(i\) 子树内(子树外的贡献可以忽略不计),然后对于 \(i\) 子树内当成一棵树做 \(x=0\) 即可。因为树形态随机,所以时间复杂度 \(O(\sum_i siz_i)=O(n\log n)\)

int n,a[maxn];
vector<int>G[maxn];
int root[maxn];
int siz[maxn];
vector<int>v[maxn];
int fa[maxn];
double f[maxn],p[maxn];
double sum,res;
int dfn[maxn],dfncnt,nfd[maxn];
void dfs0(int x){
	dfn[x]=++dfncnt,nfd[dfncnt]=x,siz[x]=1;
	for(int u:G[x])dfs0(u),siz[x]+=siz[u];
}
void dfs(int x){
	sum+=f[x],res+=f[x]*p[x];
	for(int u:G[x]){
		f[u]=f[x]*siz[u]/siz[x]/p[u];
		dfs(u);
	}
}
double solve(int d){
	const int rt=root[d];
	sum=res=0,f[rt]=1;
	rep(i,dfn[rt],dfn[rt]+siz[rt]-1){
		const int u=nfd[i];
		p[u]=1.0*((a[u]+d)%n)/n;
	}
	dfs(rt);
	return res/sum;
}
inline void solve_the_problem(){
	n=rd();
	rep(i,1,n)fa[i]=rd(),G[fa[i]].emplace_back(i);
	rep(i,1,n)a[i]=rd(),root[(n-a[i])%n]=i;
	dfs0(1);
	double ans=0;
	rep(i,0,n-1)ckmx(ans,solve(i));
	printf("%.12lf",ans);
}
posted @ 2025-02-17 19:09  dcytrl  阅读(22)  评论(0)    收藏  举报