专栏文章
题解:CF2028E Alice's Adventures in the Rabbit Hole
CF2028E题解参与者 1已保存评论 1
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 1 条
- 当前快照
- 1 份
- 快照标识符
- @miqmwg7v
- 此快照首次捕获于
- 2025/12/04 07:24 3 个月前
- 此快照最后确认于
- 2025/12/04 07:24 3 个月前
挺有意思的一道题。
设 表示在 的儿子当中最靠近叶节点的儿子。显然这个东西可以直接搜索出来。
以下设 。
设 表示 Alice 从 爬到根的概率。
分两种情况:
分两种情况:
- 这次由她走。因为她想跑掉,所以她会选择更靠近根节点的点走,那她肯定是选父节点,则概率为 。
- 这次由女王走。因为女王想杀死她,所以肯定会将她拉到一个最靠近叶节点的位置,同时只能移动一步,所以这个点一定是 ,则概率为 。
所以可以得出:
乘以 是因为两种情况要平摊 的概率。
显然,这个东西有后效性无法转移,所以要让它变一下形式。

由此引发猜想: 可以表示成 的形式,那我们尝试解一下。
有:
。
所以我们就只需要将 递归求出,再递归求出 就好了。
关于取模的话,用逆元求出就好了。
代码
CPP#include<iostream>
#include<cstring>
using namespace std;
int n;
const int N=5e5+10,mod=998244353;
int h[N],e[N],ne[N],idx,g[N],dep[N];
void add(int a,int b){
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
long long f[N],k[N];
int la;
void init(){
for(int i=1;i<=la;i++){
h[i]=-1,f[i]=k[i]=g[i]=dep[i]=0;
}
idx=0;
}
long long pow(long long a,int b){
long long res=1;
while(b){
if(b&1){
res=res*a%mod;
}
a=a*a%mod;
b>>=1;
}
return res;
}
long long ny(long long a,long long b){
return a*pow(b,mod-2)%mod;
}
void dfs1(int u,int fa){
dep[u]=2e9;
int cnt=0;
for(int i=h[u];~i;i=ne[i]){
int j=e[i];
if(j==fa){
continue;
}
cnt++;
dfs1(j,u);
dep[u]=min(dep[u],dep[j]+1);
if(dep[j]+1==dep[u]){
g[u]=j;
}
}
if(!cnt){
dep[u]=0;
}
}
void dfs2(int u,int fa){
int cnt=0;
for(int i=h[u];~i;i=ne[i]){
int j=e[i];
if(j==fa){
continue;
}
cnt++;
dfs2(j,u);
}
if(cnt){
int v=g[u];
k[u]=ny(1ll,(2-k[v]+mod)%mod);
}
}
void dfs3(int u,int fa){
for(int i=h[u];~i;i=ne[i]){
int j=e[i];
if(j==fa){
continue;
}
f[j]=k[j]*f[u]%mod;
dfs3(j,u);
}
}
int main(){
int t;
cin>>t;
la=N-1;
while(t--){
init();
scanf("%d",&n);
for(int i=1;i<n;i++){
int a,b;
scanf("%d%d",&a,&b);
add(a,b),add(b,a);
}
dfs1(1,-1);
dfs2(1,-1);
f[1]=1ll;
dfs3(1,-1);
for(int i=1;i<=n;i++){
printf("%lld ",f[i]);
}
printf("\n");
la=n;
}
return 0;
}
相关推荐
评论
共 1 条评论,欢迎与作者交流。
正在加载评论...