#3328. 开箱子(unboxing)

题目描述

开箱子是守望先锋中一项重要的活动, 50 50 50 箱多少金决定了你到底是欧皇还是部落酋长。

现在我们假设有两种箱子,一种是你升级得的,另一种是氪金的,分别有一个参数 p 1 , p 2 p_1,p_2 p1,p2,你有 1 p ( 1 − 1 p ) k − 1 \frac{1}{p}(1- \frac{1}{p})^{k-1} p1(1p1)k1的概率在得到箱子的 k k k 秒后开箱,注意箱子是一个一个给你的,也就是说上一个箱子开完后下一个箱子才会开始算时间。

现在有 l 1 l_1 l1 个升级得到的箱子, l 2 l_2 l2个氪金得到的箱子,两种箱子的第一个箱子是同时间给你的,告诉你 p 1 , p 2 p_1,p_2 p1,p2,问你升级得到的箱子开完的时间严格小于氪金的箱子开完的时间的概率,为了避免精度问题,输出对 998244353 998244353 998244353 取模。

数据范围

对于所有数据满足 l 1 , l 2 ∈ [ 0 , 2 × 1 0 3 ] , p 1 , p 2 ∈ [ 1 , 1 0 9 ] l_1,l_2 \in [0,2 \times 10^3],p_1,p_2 \in [1,10^9] l1,l2[0,2×103],p1,p2[1,109] ,我们规定 0 0 = 1 0^0=1 00=1

题解

挺简单的一道题考场想歪了哭辽

考虑 d p dp dp f i , j f_{i,j} fi,j 表示升级箱开了 i i i 个,氪金箱开了 j j j 个的概率

考虑主动转移,如果升级箱开了第 i + 1 i+1 i+1 个,则可以列出转移式子:
f i + 1 , j + = f i , j × 1 p 1 × ( 1 − 1 p 2 ) × ( 1 1 − ( 1 − 1 p 1 ) × ( 1 − 1 p 2 ) ) f_{i+1,j}+=f_{i,j} \times \frac{1}{p_1} \times (1-\frac{1}{p_2}) \times (\frac{1}{1-(1-\frac{1}{p_1})\times(1-\frac{1}{p_2})}) fi+1,j+=fi,j×p11×(1p21)×(1(1p11)×(1p21)1)

最后这个是中途没有人选的概率

剩下的转移类似,注意到i=n或者j=m的时候不能转移、

效率: O ( l 1 × l 2 ) O(l_1 \times l_2) O(l1×l2)

代码

#include <bits/stdc++.h>
using namespace std;
const int P=998244353,N=2005;
int n,m,p,q,f[N][N],s,w;
int K(int x){
	int z=1;
	for (int y=P-2;y;y>>=1,x=1ll*x*x%P)
		if (y&1) z=1ll*z*x%P;
	return z;
}
int main(){
	cin>>n>>m>>p>>q;f[0][0]=1;
	p=K(p);q=K(q);w=K(1-1ll*(1-p)*(1-q)%P);
	for (int i=0;i<n;i++)
		for (int j=0;j<m;j++){
			(f[i+1][j]+=1ll*f[i][j]*p%P*(1-q)%P*w%P)%=P;
			(f[i][j+1]+=1ll*f[i][j]*q%P*(1-p)%P*w%P)%=P;
			(f[i+1][j+1]+=1ll*f[i][j]*p%P*q%P*w%P)%=P;
		}
	for (int j=0;j<m;j++) (s+=f[n][j])%=P;
	return printf("%d\n",(s+P)%P),0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值