F、take(期望+树状数组)

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<= n <= 100000 
 
1<=p[i]*100 <=100 
 
1<=d[i]<=10^9 
 
示例 1 输入 3 50 1 50 2 50 3 输出 499122178

题目大概:

有n个盒子,每个盒子都有pi的概率有di大小的钻石,刚开始手里有0大小的钻石,如果从前往后走,手中钻石比盒子钻石小,就要交换,问总的期望的交换次数。

思路:

和前几天做的那到期望的题一样。

首先套路,期望的线性性,和的期望等于期望的和,转化为求每个盒子交换的期望。

然后分析,每个盒子只能交换0次,1次。0次的不说。每个盒子交换的前提是,在它前面有比它大的盒子已经打开。所以,1次的期望就是1*(它前面比它大的盒子的不打开的概率)*它打开的概率。

然后直接求解是n2,用树状数组,nlogn求解。

代码:

#include <bits/stdc++.h>

using namespace std;
#define ll long long
const int maxn=1e5+10;
const int mod=998244353;
const int INF=0x3f3f3f3f;
struct point
{
    ll p,d,id;
}G[maxn];

long long pow_mod(long long a,long long b,long long m)
{
    a=a%m;
    long long ans=1;
    while(b)
    {
        if(b&1)
        {
            ans=(ans*a)%m;
            b--;
        }
        b>>=1;
        a=a*a%m;
    }
    return ans;
}
bool cmp(const point &a,const point &b)
{
    if(a.d>b.d)return 1;
    else if(a.d==b.d)
    {
        return a.id<b.id;
    }
    return 0;
}
ll c[maxn];
ll lowbit(ll x)
{
    return x&(-x);
}
void add(ll x,ll v)
{
    while(x<maxn)
    {
        c[x]=(c[x]*v)%mod;
        x+=lowbit(x);
    }
}
ll Sum(int x)
{
    ll sum=1;
    while(x>0)
    {
        sum=(sum*c[x])%mod;
        x-=lowbit(x);
    }
    return sum;
}
int main()
{
    int n;
    scanf("%d",&n);
    ll inv=pow_mod(100,mod-2,mod);
    for(int i=1;i<=maxn;i++)c[i]=1;
    for(int i=1;i<=n;i++)
    {
        scanf("%lld%lld",&G[i].p,&G[i].d);
        G[i].id=i;
    }
    sort(G+1,G+1+n,cmp);
    ll sum=0;
    for(int i=1;i<=n;i++)
    {
        ll id=G[i].id;
        ll p=G[i].p;
        ll sum_1=(Sum(id-1)*((inv*p)%mod))%mod;
        sum=(sum+sum_1)%mod;
        add(id,inv*(100-p)%mod);
    }
    printf("%lld\n",sum);
    return 0;
}
/*
3
50 1
50 2
50 3
*/

猜你喜欢

转载自blog.csdn.net/a1046765624/article/details/81388585