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),u\neq x}f_u\):
而不难发现 \(\sum_{u\in anc(x),u\neq x}f_u(1-p_u)\frac{siz_{fa}}{siz_u}=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);
}

浙公网安备 33010602011771号