zoukankan      html  css  js  c++  java
  • 2018牛客网暑期ACM多校训练营(第五场) F

    题目链接: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

    输入

    3
    50 1
    50 2
    50 3

    输出

    499122178

    备注:

    1<= n <= 100000

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

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

    题意:

    有n个盒子,每个盒子里有p[i]的概率有一颗d[i]大小的钻石,Kanade现在手上有一颗0大小的钻石,他遇到比手上大的钻石就会进行交换,

    现在Kanade从1~n打开盒子,计算交换次数的期望。

    Notice:

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

    这句话提示我们如何用整数表示小数,我们定 (p/100)%998244353 = d%998244353,这个d满足 (100*d)%998244353 = p%998244353,

    这个整数d,就相当于p/100。

    题解:

    对于第 i 个盒子,选取这颗钻石进行交换的概率是:前面 1 ~ i-1 颗钻石中比这颗大的那些,都没有出现的概率,乘上当前这颗钻石出现的概率,

    即 $pleft[ i ight]prodlimits_{j < i,dleft[ i ight] < dleft[ j ight]} {left( {1 - pleft[ j ight]} ight)}$,

    而交换次数的期望,就等于求和:“每个盒子交换的概率乘以交换1次(数值上就等于概率)”。

    但是不可能 $Oleft( {n^2 } ight)$ 过,所以考虑前缀优化,我们可以用树状数组维护原序列的前缀积,

    再把盒子按 $dleft[ i ight]$ 降序排序,然后进行枚举,

    此时,对于第 i 个盒子,比体积它大的都已经计算过了,都存在树状数组里了,就可以直接查询。

    (参考:https://www.nowcoder.com/discuss/89992?type=101&order=0&pos=1&page=0

    AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=100000+10;
    const ll MOD=998244353;
    
    int n;
    struct Box{
        ll p,d;
        int id;
    }box[maxn];
    bool cmp(Box a,Box b)
    {
        if(a.d==b.d) return a.id<b.id;
        return a.d>b.d;
    }
    
    struct _BIT //单点增加,区间查询
    {
        int n;
        ll C[maxn];
        int lowbit(int x){return x&(-x);}
        void init(int n)
        {
            this->n=n;
            for(int i=1;i<=n;i++) C[i]=1;
        }
        void add(int pos,ll val) //在pos点乘上val
        {
            while(pos<=n)
            {
                C[pos]=C[pos]*val%MOD;
                pos+=lowbit(pos);
            }
        }
        ll ask(int pos) //查询1~pos点的积
        {
            ll ret=1;
            while(pos>0)
            {
                ret=ret*C[pos]%MOD;
                pos-=lowbit(pos);
            }
            return ret;
        }
    }BIT;
    
    ll pow(ll a,ll b) //快速幂
    {
        ll r=1,base=a%MOD;
        while(b){
            if(b&1) r*=base , r%=MOD;
            base*=base;
            base%=MOD;
            b>>=1;
        }
        return r;
    }
    ll inv(ll a){return pow(a,MOD-2);} //求逆元
    
    int main()
    {
        cin>>n;
        BIT.init(n);
        for(int i=1;i<=n;i++)
        {
            cin>>box[i].p>>box[i].d;
            box[i].id=i;
        }
        sort(box+1,box+n+1,cmp);
    
        ll inv100=inv(100);
        ll ans=0;
        for(int i=1;i<=n;i++)
        {
            ans+=(box[i].p*inv100)%MOD * BIT.ask(box[i].id-1)%MOD;
            ans%=MOD;
            BIT.add(box[i].id,(100-box[i].p)*inv100%MOD);
        }
        cout<<ans<<endl;
    }
  • 相关阅读:
    【C语言程序设计】C语言渔夫打鱼晒网问题!
    【C语言】很少人真正了解 和 有什么区别!
    【C语言程序设计】C语言求亲密数!
    新手程序员该如何打造自己的个人品牌!谨记,共勉!
    【C语言程序设计】利用数组解决线性代数中的矩阵转置问题!
    【程序员段子】程序员太苦逼了,苍天啊!请给我一次重新择业的机会吧!
    27. Remove Element
    Leetcode Scratching Recorder
    Activity---弹出右侧窗口
    ViewPageIndicator--仿网易的使用
  • 原文地址:https://www.cnblogs.com/dilthey/p/9420747.html
Copyright © 2011-2022 走看看