牛客网暑期ACM多校训练营(第五场)F-take(树状数组)

                                                  F-take

 

传送门

题意:从左往右依次看箱子,箱子里有pi的概率存在大小为di的diamond,每次看到比自己大的diamond就会换掉自己手上的diamond,问看完箱子换取diamond的期望.

这题其实不难,仔细一想就可以发现会贡献期望的就是之前比自己大的全都没选的概率乘选取当前diamond的概率所得的概率期望,用树状数组维护选取与不选的概率期望后缀的积就可以解决了.

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
const int mod=998244353;
int n,pos;

ll bit[maxn];
ll p[maxn],d[maxn];
ll sc[maxn];

int lowbit(int x)
{
    return x&-x;
}
void add(int x,ll y)
{
    x=pos-x+1;
    while(x<=pos)
    {
        bit[x]=(bit[x]*y)%mod;
        x+=lowbit(x);
    }
}
ll sum(int x)
{
    x=pos-x+1;
    ll ans=1;
    while(x)
    {
        ans=(bit[x]*ans)%mod;
        x-=lowbit(x);
    }
    return ans;
}

ll powmod(ll a,ll b)
{
    ll ans=1;
    while(b)
    {
        if(b&1) ans=(ans*a)%mod;
        a=(a*a)%mod;
        b>>=1;
    }
    return ans;
}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%lld%lld",&p[i],&d[i]),sc[i]=d[i],p[i]=p[i]*powmod(100ll,mod-2)%mod;
    sort(sc+1,sc+1+n);
    pos=unique(sc+1,sc+1+n)-sc;
    for(int i=1;i<=n;i++) d[i]=lower_bound(sc+1,sc+pos,d[i])-sc,bit[i]=1;
    ll ans=0;
    for(int i=1;i<=n;i++) ans=(ans+sum(d[i])*p[i])%mod,add(d[i],(1-p[i])%mod);
    printf("%lld\n",(ans+mod)%mod);
}

猜你喜欢

转载自blog.csdn.net/Murphyc/article/details/81385775