一道简单题

发布时间 2023-10-16 07:45:20作者: yanghanyv

来源

在省选模拟赛中读错了 T2 的题面,于是得到了一道比原题简单很多的题。

题目描述

给定一颗 \(n\) 个点的树和一个结束节点 \(w\)
设当前所在点为 \(u\),定义一次移动过程如下:

  • \(1\)\(n\) 中随机一个点,记作 \(v\)
  • 沿着从 \(u\)\(v\) 的唯一简单路径移动一步,特别地,如果 \(u=v\) 则不移动。

当移动到 \(w\) 时,停止移动。
\(E(i)\) 为从 \(i\) 开始移动直到到达 \(w\) 的期望步数(对 \(10^9+7\) 取模)。
\(\sum\limits_{i=1}^{n}{E(i) \operatorname{xor} i}\)

数据范围

\(1 \leq w \leq n \leq 10^6\)

解法

对于叶节点:

\[E_i = \frac{n-1}{n}E_{fa_i} + \frac{1}{n}E_i + 1\\ E_i = E_{fa_i} + \frac{n}{n-1}\\ f_i = 1\\ g_i = \frac{n}{n-1}\\ \]

对于非叶节点:

\[E_i = 1 + \frac{1}{n}E_i + \frac{n-sz_i}{n}E_{fa_i} + \sum\limits_{j\in son_i}{\frac{sz_j}{n}E_j}\\ E_i = 1 + \frac{1}{n}E_i + \frac{n-sz_i}{n}E_{fa_i} + \sum\limits_{j\in son_i}{\frac{sz_j}{n}(f_jE_i + g_j)}\\ (\frac{n-1}{n} - \sum\limits_{j\in son_i}{\frac{sz_jf_j}{n}})E_i - 1 - \sum\limits_{j\in son_i}{\frac{sz_jg_j}{n}} = \frac{n-sz_i}{n}E_{fa_i}\\ \]

令:

\[p = \frac{n-1}{n} - \sum\limits_{j\in son_i}{\frac{sz_jf_j}{n}}\\ q = 1 + \sum\limits_{j\in son_i}{\frac{sz_jg_j}{n}}\\ r = \frac{n-sz_i}{n}\\ \]

带入可得:

\[pE_i - q = rE_{fa_i}\\ E_i = \frac{r}{p}E_{fa_i} + \frac{q}{p}\\ f_i = \frac{r}{p}\\ g_i = \frac{q}{p}\\ \]

代码:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e6+5;
const int MOD=1e9+7;
void exgcd(int a,int &x,int b,int &y){
	if(!b){
		x=1;
		y=0;
	}else{
		exgcd(b,y,a%b,x);
		y-=a/b*x;
	}
}
int Inv(int x){
	int res,y;
	exgcd(x,res,MOD,y);
	return (res%MOD+MOD)%MOD;
}
int Add(int a,int b){
	return a+b>=MOD?a+b-MOD:a+b;
}
int Sub(int a,int b){
	return a-b<0?a-b+MOD:a-b;
}
int Mul(int a,int b){
	return 1ll*a*b%MOD;
}
int Div(int a,int b){
	return 1ll*a*Inv(b)%MOD;
}
int n,w,gleaf,inn,sz[N],f[N],g[N],E[N];
int id,h[N],e[2*N],ne[2*N];
bool vis[N];
ll ans;
void add(int a,int b){
	id++;
	ne[id]=h[a];
	h[a]=id;
	e[id]=b;
}
void dfs1(int x){
	vector<int> son;
	vis[x]=1;
	for(int i=h[x];i;i=ne[i]){
		if(!vis[e[i]]){
			son.push_back(e[i]);
			dfs1(e[i]);
			sz[x]+=sz[e[i]];
		}
	}
	sz[x]++;
	if(sz[x]==1){
		f[x]=1;
		g[x]=gleaf;
	}else{
		int p=Sub(1,inn),q=1;
		for(int i=0;i<(int)son.size();i++){
			p=Sub(p,Mul(Mul(sz[son[i]],f[son[i]]),inn));
			q=Add(q,Mul(Mul(sz[son[i]],g[son[i]]),inn));
		}
		f[x]=Div(n-sz[x],Mul(p,n));
		g[x]=Div(q,p);
	}
}
void dfs2(int x){
	vis[x]=1;
	for(int i=h[x];i;i=ne[i]){
		if(!vis[e[i]]){
			E[e[i]]=Add(Mul(f[e[i]],E[x]),g[e[i]]);
			dfs2(e[i]);
		}
	}
}
int main(){
	scanf("%d",&n);
	inn=Inv(n);
	gleaf=Div(n,n-1);
	for(int i=2;i<=n;i++){
		int fp;
		scanf("%d",&fp);
		add(fp,i);
		add(i,fp);
	}
	scanf("%d",&w);
	dfs1(w);
	memset(vis,0,sizeof(vis));
	dfs2(w);
	for(int i=1;i<=n;i++){
		ans+=E[i]^i;
	}
	printf("%lld",ans);
	return 0;
}