树
这道题虽然已经做过多次,但比赛时还是不会做。
看了题解之后,我觉得要是我自己想肯定是做不出来的 qwq
————————————————————————————————
f[i]表示i到fath[i]的期望步数,g[i]表示fath[i]到i的期望步数
仔
细
想
想
这
个
做
法
挺
显
然
的
,
因
为
要
输
入
多
组
u
,
v
,
所
以
只
有
这
样
才
能
在
l
o
g
的
时
间
里
求
出
期
望
长
度
仔细想想这个做法挺显然的,因为要输入多组u,v,所以只有这样才能在log的时间里求出期望长度
仔细想想这个做法挺显然的,因为要输入多组u,v,所以只有这样才能在log的时间里求出期望长度
推一下式子
f
[
i
]
=
(
1
/
d
e
g
[
i
]
)
+
(
1
/
d
e
g
[
i
]
)
∗
∑
v
∈
s
o
n
[
i
]
(
1
+
f
[
v
]
+
f
[
s
]
)
f[i]=(1/deg[i])+(1/deg[i])*\sum{v∈son[i]}(1+f[v]+f[s])
f[i]=(1/deg[i])+(1/deg[i])∗∑v∈son[i](1+f[v]+f[s])
g
[
i
]
=
(
1
/
d
e
g
[
f
a
t
h
[
i
]
]
)
+
(
1
/
d
e
g
[
f
a
t
h
[
i
]
]
)
∗
∑
v
∈
s
o
n
[
f
a
t
h
[
i
]
]
,
v
!
=
i
(
1
+
f
[
v
]
+
g
[
s
]
)
+
(
1
/
d
e
g
[
f
a
t
h
[
i
]
]
)
∗
(
1
+
g
[
f
a
[
s
]
]
+
g
[
s
]
)
g[i]=(1/deg[fath[i]])+(1/deg[fath[i]])*\sum{v∈son[fath[i]],v!=i}(1+f[v]+g[s])+(1/deg[fath[i]])*(1+g[fa[s]]+g[s])
g[i]=(1/deg[fath[i]])+(1/deg[fath[i]])∗∑v∈son[fath[i]],v!=i(1+f[v]+g[s])+(1/deg[fath[i]])∗(1+g[fa[s]]+g[s])
推一推式子,得到
g[v]=deg[s]+g[s]+sum[s]-f[v]
f[s]=deg[s]+sum[s]
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
ll mod=1e9+7;
ll ksm(ll x,ll pow){
ll ans=1,res=x;
while(pow){
if(pow&1) ans=ans*res%mod;
res=res*res%mod;
pow>>=1;
}
return ans;
}
ll ny(ll x){return ksm(x,mod-2);}
int n,Q,head[N],cnt=0;
struct edge{
int link,v;
}q[N<<1];
void put(int x,int y){
q[++cnt].v=y;
q[cnt].link=head[x];
head[x]=cnt;
}
int f[N],g[N],deg[N],sum[N],fath[N];
void dfs(int s,int fa){
sum[s]=0;
for(int i=head[s];i;i=q[i].link){
int v=q[i].v;
if(v==fa) continue;
fath[v]=s;
deg[s]++;deg[v]=1;
dfs(v,s);
sum[s]=(sum[s]+f[v])%mod;
}
f[s]=(deg[s]+sum[s])%mod;
}
void dfs2(int s,int fa){
for(int i=head[s];i;i=q[i].link){
int v=q[i].v;
if(v==fa) continue;
g[v]=((deg[s]+g[s])%mod+(1ll*sum[s]-f[v]+mod)%mod)%mod;
dfs2(v,s);
}
}
int ff[N][21],ss[N][21][2],lg[N],depth[N];
void get_f(int s,int fa){
for(int i=head[s];i;i=q[i].link){
int v=q[i].v;
if(v==fa) continue;
depth[v]=depth[s]+1;
ff[v][0]=s,ss[v][0][0]=f[v],ss[v][0][1]=g[v];
for(int j=1;j<=lg[depth[v]];j++){
ff[v][j]=ff[ff[v][j-1]][j-1];
ss[v][j][0]=(ss[v][j-1][0]+ss[ff[v][j-1]][j-1][0])%mod;
ss[v][j][1]=(ss[v][j-1][1]+ss[ff[v][j-1]][j-1][1])%mod;
}
get_f(v,s);
}
}
ll ans=0;
void find(int x,int y){
if(depth[x]<depth[y]){
int jp=lg[depth[y]-depth[x]];
while(depth[x]!=depth[y]){
ans=(ans+ss[y][jp][1])%mod;
y=ff[y][jp];
jp=lg[depth[y]-depth[x]];
}
if(x==y) return;
}
if(depth[y]<depth[x]){
int jp=lg[depth[x]-depth[y]];
while(depth[x]!=depth[y]){
ans=(ans+ss[x][jp][0])%mod;
x=ff[x][jp];
jp=lg[depth[x]-depth[y]];
}
if(x==y) return;
}
int up=lg[depth[x]];
for(int i=up;i>=0;i--){
if(ff[x][i]!=ff[y][i]){
ans=(ans+ss[x][i][0])%mod;
ans=(ans+ss[y][i][1])%mod;
x=ff[x][i],y=ff[y][i];
}
}
ans=(ans+ss[x][0][0])%mod;
ans=(ans+ss[y][0][1])%mod;
}
int main(){
scanf("%d%d",&n,&Q);
for(int i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
put(u,v),put(v,u);
}
lg[1]=0;
for(int i=2;i<=n;i++){lg[i]=lg[i>>1]+1;}
dfs(1,0),f[1]=0;
g[1]=0,dfs2(1,0);
get_f(1,0);
while(Q--){
int u,v;
ans=0;
scanf("%d%d",&u,&v);
if(u==v){
puts("0");
continue;
}
find(u,v);
printf("%lld\n",ans);
}
}