CF1781F 题解
容易想到把括号变成 。考虑括号序列合法等价于前缀和 ,我们可以想加入 或 对前缀的影响。
设加入的位置的前一位前缀和为 ,则加入 相当于把 替换为 ,加入 相当于把 替换为 。
则原问题等价于初始给定一个集合 ,有 次操作,每次等概率地选择集合中的一个元素 ,并有 的概率把 加入 ,有 的概率把 加入 ,求 次操作后 中所有元素非负的概率。
显然概率转方案,最终除以 。
令 表示进行了 次操作,初始在集合中的数为 的方案数,最终答案就是 。则
解释一下:比如果加入 是求方案数,我们就枚举新加入的 在之后基于它们各进行了几次操作,就是枚举 ,然后剩下的 次操作就是基于原来在集合中的 操作。
由于顺序不一定要乘上一个系数(就是那里的阶乘)。加号右半边也是同理。
这时复杂度是 ,不能接受,显然考虑前缀和优化。
我们发现加号左右两边很像啊,于是考虑交换求和顺序,先枚举 ,这时 我们把它变为 。
则 。
令 ,则 。
这样复杂度就是 了,可以接受。
有一点要注意,就是初始化我们要假设所有 都为 ,因为我们这样 是假定初始所有数都可能出现。这样所有 。
#include<bits/stdc++.h>
#define LL long long
#define fr(x) freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);
using namespace std;
const int N=505,mod=998244353;
int n,p,P,jc[N],inv[N],f[N][N],g[N][N],s=1;
inline int ksm(int x,int p){int s=1;for(;p;(p&1)&&(s=1ll*s*x%mod),x=1ll*x*x%mod,p>>=1);return s;}
inline int C(int n,int m){return 1ll*jc[n]*inv[m]%mod*inv[n-m]%mod;}
int main()
{
scanf("%d%d",&n,&p);p=796898467ll*p%mod;P=(mod+1-p)%mod;
jc[0]=1;for(int i=1;i<=n;i++) jc[i]=1ll*jc[i-1]*i%mod;
inv[n]=ksm(jc[n],mod-2);for(int i=n-1;i>=0;i--) inv[i]=1ll*inv[i+1]*(i+1)%mod;
for(int i=0;i<=n;i++) f[0][i]=g[0][i]=1;for(int i=1;i<=n*2;i+=2) s=1ll*s*i%mod;
for(int i=1;i<=n;i++)
for(int j=0;j<=n;j++)//f{i,j}
{
for(int k=0;k<=i-1;k++) f[i][j]=(f[i][j]+(1ll*p*f[k][j+1]+(j>0?1ll*P*f[k][j-1]:0))%mod*C(i-1,k)%mod*g[i-1-k][j])%mod;
for(int k=0;k<=i;k++) g[i][j]=(g[i][j]+1ll*C(i,k)*f[k][j]%mod*f[i-k][j])%mod;
}
printf("%d",1ll*f[n][0]*ksm(s,mod-2)%mod);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现