• 牛客多校第五场 F take


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

    题目描述

    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

    题意:开始手中有一个大小为0的钻石,然后给出n个箱子,有x/100的概率开出y大小的钻石,如果比手中的钻石大的话就交换,求交换次数

    思路:这个牵扯到一些数学知识,我们单独算每个箱子得贡献,如果我要交换当前箱子的钻石,说明当前箱子一定要能开出钻石,所以要乘以当前得概率
    然后既然当前箱子要交换,说明当前得钻石说明肯定比手中得钻石大,也就是说前面比这个箱子大得钻石都没有开出钻石,也就是要再乘以前面比它大得
    钻石得失败概率,比它小的钻石开不开出钻石都不影响当前钻石,所以概率为1
    所以每个箱子得贡献为: 比当前钻石大得箱子开钻石失败得概率 * 当前钻石成功概率
    但是我们这样取间断的概率有点麻烦,我们这里用树状数组维护前缀积,优化了一下
    我们还要注意,我们的数的范围是1e9 但是箱子的个数是1e5,
    1e9的数组我们开不了,所以我们需要离散化
    还有我们分数取模无法取,所以我们还要使用逆元来计算

    下面看代码注释
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #define maxn 998244353
    using namespace std;
    typedef long long ll;
    struct sss
    {
        ll id,x;
    }a[100001];
    ll inv;
    ll d[100001],c[100001];
    ll n,cnt;
    ll qpow(ll a,ll n)
    {
        ll ans=1;
        while(n)
        {
            if(n%2) ans=(ans*a)%maxn;
            a=(a*a)%maxn;
            n>>=1;
        }
        return ans;
    }
    ll lowbit(ll x)
    {
        return x&(-x);
    }
    ll sum(ll x)//因为我们要求的是比当前大的钻石概率,而模版树状数组是求小的,我们就反过来即可
    {
        ll ans=1;
        while(x<=n)
        {
            ans=(ans*c[x])%maxn;
            x+=lowbit(x);
        }
        return ans;
    }
    void updata(ll x,ll d)//同上
    {
        while(x>0)
        {
            c[x]=(c[x]*d)%maxn;
            x-=lowbit(x);
        }
    }
    int main()
    {
        scanf("%lld",&n);
        inv=qpow(100,maxn-2);//计算分母100的逆元
        for(int i=1;i<=n;i++)
        {
            scanf("%lld%lld",&a[i].id,&a[i].x);
            d[i-1]=a[i].x;
        }
        sort(d,d+n);//离散化
        cnt=unique(d,d+n)-d;
        for(int i=1;i<=n;i++)
        {
            c[i]=1;//初始化前缀积数组
            a[i].x=upper_bound(d,d+cnt,a[i].x)-d+1;
        }
        ll ans=0;
        for(int i=1;i<=n;i++)
        {
            ans = (ans + (1LL * sum(a[i].x) * a[i].id % maxn * inv)) % maxn;//把前面把他大的箱子的失败概率乘以当前成功的概率
            updata(a[i].x, 1LL * (100 - a[i].id)*inv % maxn);//更新树状数组  注意是100-当前概率  因为我们要存的是失败概率
        }
        printf("%lld",ans);
    }
  • 相关阅读:
    hibernate理解
    struts理解
    网上书城项目
    编码过程中遇到的问题
    JS回调函数
    requirejs 一个拆分js项目的类库
    jq插件开发总结
    转载-- 魔兽哈希算法封装和测试
    转载--C# PLINQ 内存列表查询优化历程
    Oracle删除死锁进程的方法
  • 原文地址:https://www.cnblogs.com/Lis-/p/9412244.html
Copyright © 2020-2023  润新知