1. 程式人生 > >一中模擬賽10.20&10.27——tree1.0&2.0

一中模擬賽10.20&10.27——tree1.0&2.0

Tree1.0

Description

選擇起始點和終點以後,會每次等概率隨機走到一個相鄰的點(不能來回走同一條邊多次),問最後走到終點的期望步數

Solution

統計下子樹內和子樹外的點分別作為起點和終點的貢獻即可

Code

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=100001;
struct node{
	int to,ne;
}e[N<<1];
ll ans;
int SX,SY,X[N],Y[N],i,x,y,tot,h[
N],sz[N],n; inline char gc(){ static char buf[100000],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; } inline int rd(){ int x=0,fl=1;char ch=gc(); for (;ch<48||ch>57;ch=gc())if(ch=='-')fl=-1; for (;48<=ch&&ch<=57;ch=gc())x=(x<<3)
+(x<<1)+(ch^48); return x*fl; } void add(int x,int y){ e[++tot]=(node){y,h[x]}; h[x]=tot; } void dfs(int u,int fa){ sz[u]=1; for (int i=h[u],v;i;i=e[i].ne) if ((v=e[i].to)!=fa){ dfs(v,u); sz[u]+=sz[v]; X[u]+=X[v]; ans+=1ll*Y[u]*X[v]*sz[v]; } ans+=1ll*Y[u]*(SX-X[u])*(n-sz[
u]); } int main(){ n=rd(); for (i=1;i<n;i++) x=rd(),y=rd(),add(x,y),add(y,x); for (i=1;i<=n;i++) SX+=(X[i]=rd()),SY+=(Y[i]=rd()); dfs(1,0); printf("%.9lf",ans*1.0/SX/SY); }

Tree2.0

Description

選擇起始點和終點以後,會每次等概率隨機走到一個相鄰的點(隨便怎麼走),問最後走到終點的期望步數

Solution

f [ i ] f[i] 表示i走到它父親的期望步數
g [ i ] g[i] 表示i父親走到i的期望步數
首先葉子結點 f [ i ] f[i] 都為 1 1 。對於任意非葉子節點 i i 1 / d [ i ] 1/d[i] 的概率走到父親,還有 1 / d [ i ] 1/d[i] 的概率走到各個兒子,所以 f [ i ] = 1 / d [ i ] + ( f [ s o n ] + f [ i ] + 1 ) / d [ i ] = &gt; f [ i ] = d [ i ] + f [ s o n ] f[i]=1/d[i]+(f[son]+f[i]+1)/d[i]=&gt;f[i]=d[i]+f[son]
同理 g [ i ] = 1 / d [ f a ] + ( 1 + g [ f a ] + g [ i ] ) / d [ f a ] + ( f [ s o n ] + g [ i ] + 1 ) / d [ f a ] = &gt; g [ i ] = d [ f a ] + g [ f a ] + f [ s o n ] g[i]=1/d[fa]+(1+g[fa]+g[i])/d[fa]+(f[son]+g[i]+1)/d[fa]=&gt;g[i]=d[fa]+g[fa]+f[son] s o n son f a fa 的兒子,且 s o n ! = i son!=i
然後對於每一條邊,統計下子樹內和子樹外的點分別作為起點和終點的貢獻即可

Code

#include<bits/stdc++.h>
using namespace std;
const int N=100001,M=998244353;
struct node{
	int to,ne;
}e[N<<1];
int f[N],g[N],u,v,xx,yy,ans,sx,sy,x[N],y[N],h[N],tot,sum[N],p[N],n,i;
inline char gc(){
	static char buf[100000],*p1=buf,*p2=buf;
	return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int rd(){
	int x=0,fl=1;char ch=gc();
	for (;ch<48||ch>57;ch=gc())if(ch=='-')fl=-1;
	for (;48<=ch&&ch<=57;ch=gc())x=(x<<3)+(x<<1)+(ch^48);
	return x*fl;
}
void add(int x,int y){
	e[++tot]=(node){y,h[x]};
	h[x]=tot;
}
void ex_gcd(int a,int b,int &x,int &y){
	if (!b) x=1,y=0;
	else ex_gcd(b,a%b,y,x),y-=a/b*x;
}
void up(int u,int fa){
	if (u!=1) f[u]=1;
	for (int i=h[u],v;i;i=e[i].ne)
		if ((v=e[i].to)!=fa) up(v,u),f[u]+=f[v]+1;
}
void down(int u,int fa){
	for (int i=h[u],v;i;i=e[i].ne)
		if ((v=e[i].to)!=fa) g[v]=f[u]-f[v]+g[u],down(v,u);
}
void dfs1(int u,int fa){
	sum[u]=x[u];
	for (int i=h[u],v;i;i=e[i].ne)
		if ((v=e[i].to)!=fa) dfs1(v,u),sum[u]+=sum[v],p[u]=(p[u]+p[v]+1ll*sum[v]*f[v])%M;
}
void dfs2(int u,int fa){
	ans=(ans+1ll*p[u]*y[u])%M;
	for (int i=h[u],v;i;i=e[i].ne)
		if ((v=e[i].to)!=fa) p[v]=(p[u]-1ll*sum[v]*f[v]%M+1ll*(sx-sum[v])*g[v]%M)%M,dfs2(v,u);
}
int main(){
	n=rd();
	for (i=1;i<n;i++) u=rd(),v=rd(),add(u,v),add(v,u);
	for (i=1;i<=n;i++) x[i]=rd(),y[i]=rd(),sx+=x[i],sy+=y[i];
	up(1,0);down(1,0);
	dfs1(1,0);
	dfs2(1,0);
	ex_gcd(sx,M,xx,yy);
	ans=1ll*ans*(xx+M)%M;
	ex_gcd(sy,M,xx,yy);
	ans=1ll*ans*(xx+M)%M;
	printf("%d",(ans+M)%M);
}