概率dp AtCoder Beginner Contest 243 F
AtCoder Beginner Contest 243 F
题意
n种彩票,每种彩票i中奖概率为 ,求抽k次后恰好m种彩票中奖的概率(简化的概率,题目中的概率还要用个逆元)
思路
超几何分布,设抽k次后每种彩票i中奖个数为 ,则概率为
,化简之后就变成
这样就清晰很多了,设状态为当前第i种彩票,已经由j种彩票被抽中,抽了k次的概率;
那么有 ,即当前第i种彩票买了c张,从之前的状态转移过来
代码
const int N=55,inf=0x3f3f3f3f,mod= 998244353;
int n,m,K;
int f[N][N][N],fac[N],p[N],inv_f[N];
int q_pow(int a,int b)
{
int res=1;
while(b)
{
if(b&1) res=res*a%mod;
a=a*a%mod;
b/=2;
}
return res%mod;
}
void init(int n)
{
fac[0]=inv_f[0]=1;
for(int i=1;i<=n;i++) fac[i]=fac[i-1]*i%mod;
inv_f[n]=q_pow(fac[n],mod-2)%mod;
for(int i=n-1;i>=1;i--)
{
inv_f[i]=inv_f[i+1]*(i+1)%mod;
}
}
void solve()
{
cin>>n>>m>>K;
init(K+1);
int sum=0;
for(int i=1;i<=n;i++) cin>>p[i],sum+=p[i];//分母
int inv=q_pow(sum,mod-2)%mod;
f[0][0][0]=1;
for(int i=1;i<=n;i++) p[i]=p[i]*inv%mod;
for(int i=0;i<=n;i++)
{
for(int j=0;j<=i;j++)
{
for(int k=0;k<=K;k++)
{
for(int c=0;c+k<=K;c++)
{
f[i+1][j+(c!=0)][k+c]=(f[i+1][j+(c!=0)][k+c]+f[i][j][k]*q_pow(p[i+1],c)%mod*inv_f[c]%mod)%mod;
}
}
}
}
int ans=f[n][m][K]*fac[K]%mod;
cout<<ans<<endl;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)