牛客网暑期ACM多校训练营(第五场)take

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gtuif/article/details/81911509

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

输出

复制

扫描二维码关注公众号,回复: 3402795 查看本文章
499122178

备注:

1<= n <= 100000

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

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

题意: 有n个箱子,编号为1~n,第i个箱子有p[i]的概率箱子中有d[i]大小的钻石,Kanade 从1~n依次开箱子,若箱子中的钻石大小比他手中的大,就替换掉他手中的钻石,问替换次数的期望;

思路:概率论中学过E(X+Y) = E(X) + E(Y);那么这个题就转换为了求每个箱子替换的概率,再求和即可;思考第i个箱子发生替换的概率公式为P(i) = (1 - p[a1]) * (1 - p[a2])*……(1 - p[at]) *p[i] * 1 (t < j && d[at] > d[i]). 公式的意思是 在前i- 1个箱子中,如果有箱子比这个箱子的钻石大,就让他没有这个钻石,也即是乘以他没有钻石的概率;最后再乘以这个箱子有钻石的概率就是这个箱子发生替换的概率,再乘以1(发生替换),箱子小的就不用考虑了,因为本来就不会发生替换;但是代码暴力计算期望的复杂度是n^2的,所以要考虑其他的方法;

我们可以先对每个箱子可能拥有的钻石的大小进行排序,然后用树状数组维护前缀积,因为是从大到小排过序了,所以每次插入的钻石的大小都是比数组中的钻石大小小的,这样直接插入时统计前缀积就行了(插入的时候是按你原来箱子的编号插入的,相当于重新生成原序列且保证统计的前缀积是比他大的且位置在他前面的箱子(膜大佬ORZ));最后注意的地方就是因为统计的是前缀积,所以数组初始化为1;

下面附上我的代码:

#include<bits/stdc++.h>
#define lowbit(x) x & -x
using namespace std;
typedef long long ll;
const int mod = 998244353;
const int maxn = 1e5 + 10;
struct node
{
    ll id,p,d;
}a[maxn];
ll quick_mod(ll a, ll b)
{
    ll ans = 1;
    a = a % mod;
    while(b)
    {
        if(b & 1) ans = (ans * a) % mod;
        b >>= 1;
        a = (a * a) % mod;
    }
    return ans;
}
ll exsum[maxn];
ll n;
void add(ll p, ll x)
{
    while(p <= n)
    {
        exsum[p] = (exsum[p] * x) % mod;
        p += lowbit(p);
    }
}
ll sum(ll x)
{
    ll res = 1;
    while(x > 0)
    {
        res = (res * exsum[x]) % mod;
        x -= lowbit(x);
    }
    return res;
}
bool cmp(node a, node b)
{
    if(a.d == b.d)
        return a.id < b.id;
    return a.d > b .d;
}
int main()
{
    cin >> n;
    ll inv = quick_mod(100, mod - 2);
    for(int i = 1; i <= n; i++)
    {
        exsum[i] = 1;
        scanf("%lld %lld", &a[i].p, &a[i].d);
        a[i].p = (a[i].p * inv) % mod;
        a[i].id = i;
    }
    sort(a + 1, a + n + 1, cmp);
    ll ans = 0;
    for(int i = 1; i <= n; i++)
    {
        ans += (sum(a[i].id - 1) * (a[i].p % mod));
        ans %= mod;
        add(a[i].id, (1 - a[i].p + mod)%mod);
    }
    printf("%lld\n", ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/gtuif/article/details/81911509