2021牛客多校#4 B- Sample Game

题目链接

传送门

题目大意

有一个可以生成 1 1 1 n ( 1 ≤ n ≤ 100 ) n(1 \leq n \leq 100) n(1n100)的随机数生成器,生成 x ( 1 ≤ x ≤ n ) x(1 \leq x \leq n) x(1xn)的概率为 p x p_x px
输入 W i W_i Wi p i p_i pi的计算公式为 w i ∑ j = 1 n W j \frac{w_i}{\sum^n_{j=1}W_j} j=1nWjwi.
现在一次执行以下操作:
1.随机生成一个数 x x x
2.若 x x x是之前生成的数中最大的,则执行步骤1,否则执行步骤3;
3.若共生成了 y y y个数字,则得到分数 y 2 y^2 y2
求获得分数的期望值。

题解

易得 x x x的期望为 f x = 1 × ∑ i = 1 x − 1 p i + p x ( 1 + f x ) + ∑ i = x + 1 n p i ( 1 + f i ) f_x=1 \times \sum^{x-1}_{i=1}p_i+p_x(1+f_x)+\sum^{n}_{i=x+1}p_i(1+f_i) fx=1×i=1x1pi+px(1+fx)+i=x+1npi(1+fi)
经化简得 f x = 1 + ∑ i = x + 1 n p i f i 1 − p x f_x=\frac{1+\sum\limits^{n}_{i=x+1}p_if_i}{1-p_x} fx=1px1+i=x+1npifi
由于 f ( x 2 ) ! = f ( x ) 2 f(x^2)!=f(x)^2 f(x2)!=f(x)2,所以无法直接得到结果,但 f ( x + 1 ) 2 = f ( x ) 2 + 2 f ( x ) + 1 f(x+1)^2=f(x)^2+2f(x)+1 f(x+1)2=f(x)2+2f(x)+1,所以我们可以用一个新的 d p dp dp数组来储存 f ( x ) 2 f(x)^2 f(x)2.
易得 d p x = 1 × ∑ i = 1 x − 1 p i + p x ( 1 + 2 × f x + d p x ) + ∑ i = x + 1 n p i ( 1 + 2 × f i + d p i ) dp_x=1 \times \sum^{x-1}_{i=1}p_i+p_x(1+2 \times f_x +dp_x)+\sum^{n}_{i=x+1}p_i(1+2 \times f_i+dp_i) dpx=1×i=1x1pi+px(1+2×fx+dpx)+i=x+1npi(1+2×fi+dpi)
经化简得 d p x = 1 + 2 p x f x + ∑ i = x + 1 n p i ( d p i + 2 × f i ) 1 − p x dp_x=\frac{1+2p_xf_x +\sum\limits^{n}_{i=x+1}p_i(dp_i+2 \times f_i)}{1-p_x} dpx=1px1+2pxfx+i=x+1npi(dpi+2×fi)
然后统计其中 d p i + 2 ∗ f i + 1 dp_i+2*f_i+1 dpi+2fi+1的总值
经化简得 a n s = 1 + ∑ i = 1 n p i ( d p i + 2 × f i ) ; ans=1+\sum^{n}_{i=1}p_i(dp_i+2 \times f_i); ans=1+i=1npi(dpi+2×fi);
注意结果全程要取余 m o d = 998244353 mod=998244353 mod=998244353,还要采用费马小定理即快速幂来取余(超范围的全给他模上【狗头】)。

参考代码

#include<bits/stdc++.h>
#define ll long long
const ll mod=998244353;
const int N=1e2+5;
ll dp[N],f[N],w[N],p[N],sum[N],num[N];
ll n,s;
ll pow(ll a,ll b)
{
    ll ret=1;
    while(b)
    {
        if(b&1)
            ret=ret*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return ret;
}
int main()
{
    scanf("%lld",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&w[i]);
        s+=w[i];
    }
    for(int i=1;i<=n;i++)
        p[i]=pow(s,mod-2)*w[i]%mod;
    num[n]=0;
    for(int i=n;i>=1;i--)
    {
        f[i]=(1+num[i])*pow((1+mod-p[i]),mod-2)%mod;
        num[i-1]=(f[i]*p[i]%mod+num[i])%mod;
    }
    num[n]=0;
    for(int i=n;i>=1;i--)
    {
        dp[i]=(1+2*f[i]*p[i]%mod+num[i])*pow((1+mod-p[i]),mod-2)%mod;
        num[i-1]=(p[i]*(dp[i]+2*f[i])+num[i])%mod;
    }
    printf("%lld\n",(num[0]+1)%mod);
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值