Solution - AGC060C

Link

简要题意:称一个长为 2n1 的排列 P 像堆,如果 Pi<P2i,且 Pi<P2i+1。给定 a,b,设 u=2a,v=2b+11,在所有像堆的排列中任取一个,求 Pu<Pv 的概率。

既然这个排列像堆,那就把这个问题放在满二叉树上解决。结点 i 的权值是 Pi,子结点是 2i2i+1

首先,如果把结点编号,然后按照权值排列,那么就是对这棵满二叉树做了一次拓扑排序,这里父结点向子结点连有向边。那么,我们只需要考虑结点的一个排列 S,使得 i 在其子树的前面。

题目中给定的 u,v 分别是第 a+1 层最左边的结点和第 b+1 层最右边的结点。而题目要求的 Pu<Pv 可以看作是从 uv 连了一条有向边,或者说 Su 必须在 v 前面。(下面的叙述中,涉及树的概念都是没有考虑这条边的)

这个拓扑序的开头当然是 1,然后整个图被分成了两棵满二叉树,从一棵的某个点向另一棵的某个点连边。

接下来,当然是选择一棵树的根结点。然后,这棵树又被分成了两棵树,其中有一棵是不含 u,v 之一的。那么,在安排好剩下的两棵树之后,将这棵树随意插入已有的排列即可。

想到这里,一个 DP 的方式呼之欲出:设 dpi,j 表示剩下一棵 i 层的满二叉树和一棵 j 层的满二叉树的方案数,则 dpi,j 会从 dpi1,jdpi,j1 转移而来。注意,由于 u,v 距离叶子层的深度是不变的,所以这样的状态定义已经足够。再用 fi,j 表示相应的概率。

我们还需要考虑一个普通的 i 层满二叉树的拓扑序总数。设为 Si

先求 Si 的递推式。第一步是选择根结点,然后是将两棵子树的所有排列方式放入拓扑序中。所有排列有 Si12 种。每棵子树的拓扑序长度为 2i11,所以插入的方式有 C2i22i11 种。于是

Si=Si12×C2i22i11

u,v 分别在倒数第 A,B 层,则 DP 的初始值为 fA1,j=1jB 成立。

与前面类似可得 dpi,j 的递推式为:

dpi,j=dpi1,j×Si1×C2i+2j32i11+dpi,j1×Sj1×C2i+2j32j11

又由于

fi,j=dpi,jSi×Sj×C2i+2j22i1

所以

fi,j=dpi1,j×Si1×C2i+2j32i11+dpi,j1×Sj1×C2i+2j32j11Si×Sj×C2i+2j22i1

=fi1,j×Si12×Sj×C2i1+2j22i11×C2i+2j32i11Si×Sj×C2i+2j22i1+fi,j1×Sj12×Si×C2i+2j122j11×C2i+2j32j11Si×Sj×C2i+2j22j1

=fi1,j×C2i1+2j22i11×C2i+2j32i11C2i22i11×C2i+2j22i1+fi,j1×C2i+2j122j11×C2i+2j32j11C2j22j11×C2i+2j22j1

结合

C2i1+2j22i11×C2i+2j32i11C2i22i11×C2i+2j22i1

=(2i1+2j2)!×(2i+2j3)!(2i11)!×(2j1)!×(2i11)!×(2i1+2j2)!(2i2)!×(2i+2j2)!(2i11)!×(2i11)!×(2i1)!×(2j1)!

=(2i+2j3)!×(2i1)!(2i+2j2)!×(2i2)!

=2i12i+2j2

最后我们得到了一个漂亮的表达式:

fi,j=fi1,j×2i12i+2j2+fi,j1×2j12i+2j2

答案是 fn1,n1

Code:

#include<bits/stdc++.h>
using namespace std;
const int N=5005,mod=998244353;
int n,A,B;
long long pwr2[N],p[N][N],f[N][N];
int power(int a,int b){
int c=1;
for(;b;b>>=1){
if(b&1)c=1ll*c*a%mod;
a=1ll*a*a%mod;
}
return c;
}
int main(){
scanf("%d%d%d",&n,&A,&B);
A=n-A;B=n-B;
for(int i=1;i<=n;i++)pwr2[i]=power(2,i);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
p[i][j]=(pwr2[i]-1)*power(pwr2[i]+pwr2[j]-2,mod-2)%mod;
for(int i=B;i<=n;i++)f[A-1][i]=1;
for(int i=A;i<=n;i++)
for(int j=B;j<=n;j++)
f[i][j]=(f[i-1][j]*p[i][j]%mod+f[i][j-1]*p[j][i]%mod)%mod;
printf("%d\n",f[n-1][n-1]);
return 0;
}
posted @   by_chance  阅读(60)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示