• DTOJ #3328. 开箱子(unboxing)


    【题目描述】

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

    现在我们假设有两种箱子,一种是你升级得的,另一种是氪金的,分别有一个参数 $p_1,p_2$,你有 $frac{1}{p}(1- frac{1}{p})^{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 imes 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
    ",ans);
    34 }
  • 相关阅读:
    .NET HttpWebRequest应用
    .NET 文件上传和文件接收
    小程序报错:对应的服务器 TLS 为 TLS 1.0 ,小程序要求的 TLS 版本必须大于等于 1.2
    发布微信小程序体验版
    .NET 通过entity framework报数据库连接错误:ORA-01017: invalid username/password; logon denied
    将Oracle 12c的某用户数据迁移至OracleXE的用户
    C# Oracle 时间字符串转时间类型
    在.NET中调用Java的类
    Oracle 取前几条记录
    oracle impdp将导出用户的所有对象导入至另一个用户下,生成的触发器语句问题处理
  • 原文地址:https://www.cnblogs.com/RenSheYu/p/11327057.html
Copyright © 2020-2023  润新知