DTOJ #3328. 开箱子(unboxing)

Posted rensheyu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了DTOJ #3328. 开箱子(unboxing)相关的知识,希望对你有一定的参考价值。

【题目描述】

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

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

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

【输入格式】

输入文件只有一行,四个整数 $l_1,l_2,p_1,p_2$。

【输出格式】

输出文件只有一行,一个整数表示答案。

【样例】

样例输入
输入样例1
1 2 2 1
输入样例2
3 6 8 4

样例输出
输出样例1
499122177
输出样例2
768511825

【数据范围与提示】

对于 $ 10 \% $ 的数据, $ l_1=l_2=0 $ 。

对于另外 $ 10 \% $ 的数据, $ l_1=0,l_2=1 $ 。

对于另外 $ 10 \% $ 的数据, $ l_1=1,l_2=0 $ 。

对于另外 $ 10 \% $ 的数据, $ l_1=l_2=1 $ 。

对于所有数据满足 $ l_1,l_2 \in [0,2 \times 10^3],p_1,p_2 \in [1,10^9] $ ,我们规定 $ 0^0=1 $ 。

【题解】

考虑概率 $dp$,设 $f[i][j]$ 表示取了 $i$ 个第一种盒子,$j$ 个第二种盒子的概率。显然 $f[i][j]$ 可从 $f[i-1][j],f[i][j-1],f[i-1][j-1],f[i][j]$ 转移得来。发现式子左右两端都有 $f[i][j]$,解个方程即可得到转移式。

初始值 $f[0][0]=1$,答案 $f[l1][l2]$。具体转移参见代码。

【代码】

 1 #include<bits/stdc++.h>
 2 inline int read ( void )
 3 
 4     int x=0;char ch;bool f=true;
 5     while ( !isdigit(ch=getchar()) ) if ( ch==- ) f=false;
 6     for ( x=ch^48;isdigit(ch=getchar()); ) x=(x<<1)+(x<<3)+(ch^48);
 7     return f ? x : -x ;
 8 
 9 const int mod=998244353;
10 inline int power ( int a,int b )
11 
12     int res=1;
13     for ( ;b;b>>=1,a=1LL*a*a%mod ) if ( b&1 ) res=1LL*res*a%mod;
14     return res;
15 
16 int f[2010][2010];
17 inline void Add ( int &x,int y )  x+=y;x-=(x>=mod)?mod:0; 
18 signed main()
19 
20     int l1=read(),l2=read(),p1=read(),p2=read();
21     if ( !l2 ) return !puts("0");
22     if ( !l1 ) return !puts("1");
23     int invp1=power(p1,mod-2),invp2=power(p2,mod-2);
24     int q1=(1-invp1+mod)%mod,q2=(1-invp2+mod)%mod;
25     f[0][0]=1;
26     int res=power((1-1LL*q1*q2%mod+mod)%mod,mod-2);
27     for ( int i=0;i<l1;i++ ) for ( int j=0;j<l2;j++ )
28         Add(f[i+1][j],1LL*f[i][j]*res%mod*invp1%mod*q2%mod),
29         Add(f[i][j+1],1LL*f[i][j]*res%mod*invp2%mod*q1%mod),
30         Add(f[i+1][j+1],1LL*f[i][j]*res%mod*invp1%mod*invp2%mod);
31     int ans=0;
32     for ( int i=0;i<l2;i++ ) Add(ans,f[l1][i]);
33     return !printf("%d\n",ans);
34 

 

以上是关于DTOJ #3328. 开箱子(unboxing)的主要内容,如果未能解决你的问题,请参考以下文章

2019.01.02-dtoj2293-幻想乡开店(shop)

NPCSKINS开箱,boxppp之后CSGO开箱的最新体验

今天电脑突然卡死 我重启下酒开不了机了 然后我拆开箱子一顿拔插拔插 后来开机出现那个a key结尾的英文.

最好的dota2三方开箱子网站-dota2case

RK3328芯片处理器参数介绍

前端学习(3328):闭包的形式4