zoukankan      html  css  js  c++  java
  • 牛客网暑假训练第五场——F take(树状数组求概率期望)

    链接:https://www.nowcoder.com/acm/contest/143/F
    来源:牛客网

    时间限制:C/C++ 1秒,其他语言2秒
    空间限制:C/C++ 262144K,其他语言524288K
    64bit IO Format: %lld
    题目描述
    Kanade has n boxes , the i-th box has p[i] probability to have an diamond of d[i] size.

    At the beginning , Kanade has a diamond of 0 size. She will open the boxes from 1-st to n-th. When she open a box,if there is a diamond in it and it’s bigger than the diamond of her , she will replace it with her diamond.

    Now you need to calculate the expect number of replacements.

    You only need to output the answer module 998244353.

    Notice: If x%998244353=y*d %998244353 ,then we denote that x/y%998244353 =d%998244353

    输入描述:
    The first line has one integer n.

    Then there are n lines. each line has two integers p[i]*100 and d[i].
    输出描述:
    Output the answer module 998244353
    示例1
    输入
    3
    50 1
    50 2
    50 3
    输出
    499122178
    备注:
    1<= n <= 100000

    1<=p[i]*100 <=100

    1<=d[i]<=10^9

    题意:有n个盒子,每个盒子出现大小为di的概率为pi,按id顺序遍历盒子,每次遇到比当前钻石大的就换掉,问更换次数期望。

    要保证当出现第di个大小的钻石时能更换,那么说明在此之前比其大的钻石都没拿到,那么就是这个钻石之前的比其大的钻石没拿到的概率连乘,用树状数组维护这样失败概率的前缀积,并加上计算每个钻石如果更换的概率,乘上大小,即期望。

    树状数组中存储第id个钻石没有di那么大的概率,那么,当在第id个位置更换成di那么大的钻石,就要保证在这之前的钻石都比di小

    #include<bits/stdc++.h>
    #define LL long long
    #define M(a,b) memset(a,b,sizeof a)
    #define pb(x) push_back(x)
    #define lowbit(x) x&(-x)
    using namespace std;
    const int maxn=1e5+7;
    const int p=998244353;
    LL qp(LL a,LL b)
    {
        LL ans=1;
        while(b)
        {
            if(b&1)ans=ans*a%p;
            a=a*a%p;
            b>>=1;
        }
        return ans;
    }
    struct node
    {
        LL val,id,pp;
        bool operator <(const node &a)const
        {
            if(val==a.val)return id<a.id;
            return val>a.val;
        }
    }a[maxn];
    LL tre[maxn];
    int n;
    LL inv=qp(100,p-2);///注意题目给出的都是*100之后的概率,因此要*100的逆元才是真正的概率
    void update(int pos,LL val)
    {
        for(int i=pos;i<=n;i+=lowbit(i))tre[i]=tre[i]*val%p;///树状数组计算前缀乘
    }
    LL query(int pos)
    {
        LL ans=1;
        for(int i=pos;i;i-=lowbit(i))ans=ans*tre[i]%p;
        return ans;
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%lld%lld",&a[i].pp,&a[i].val),a[i].id=i;
        sort(a+1,a+1+n);
        fill_n(tre,n,1LL);///初始化全为1
        LL ans=0;
        for(int i=1;i<=n;i++)///按钻石从大到小的顺序更新树状数组,这样每次查询时都是查询该id之前,没有取得 小于自己id,且大小比自己大的钻石的概率
        {
            ans=(ans+query(a[i].id-1)*a[i].pp%p*inv%p)%p;///先查询比自己小的id的比自己大的钻石不取的概率
            update(a[i].id,((LL)100-a[i].pp)*inv%p);///然后再更新取不到该钻石的概率到树状数组中
        }
        printf("%lld
    ",ans);
    }
    
  • 相关阅读:
    如何将JS中object转换为字符串
    验证码的实现
    JSP中解决session超时跳转到登陆页面并跳出iframe框架或局部区域的方法
    java 后台封装json数据学习总结
    ztree复选框
    左偏树详解
    Docker 入门
    linux 多进程
    派生类构造函数顺序
    20210203 7. 分库分表实战及中间件
  • 原文地址:https://www.cnblogs.com/kuronekonano/p/11135710.html
Copyright © 2011-2022 走看看