牛客网暑期ACM多校训练营(第五场)F题Take题解

考虑每一个东西对答案的贡献,即这个东西取的概率乘以前面比它大的东西不取的概率。


直接暴力计算的复杂度为O(n2)不能接受。我们可以将d从大到小排序,用树状数组维护1 - pi的前缀积。每次插入前查询在它前面比他大的概率的乘积。
(因为从大到小插入了,所以树状数组里面的插入的都是d比他大的。)
由于维护的是乘积,所以我们树状数组要初始化成1。

代码如下:

#include <bits/stdc++.h>
typedef long long ll;
const int mod = 119 << 23 | 1;
ll Pow(ll a, ll n = mod - 2)
{
    ll t = 1;
    for (; n; n >>= 1, (a *= a) %= mod)
        if (n & 1) (t *= a) %= mod;
    return t;
}
const int N = 1 << 17;
ll bit[N];
void update(int x, ll v)
{
    for (int i = x; i < N; i += i & -i) (bit[i] *= v) %= mod;
}
ll query(int x)
{
    ll t = 1;
    for (int i = x; i; i -= i & -i) (t *= bit[i]) %= mod;
    return t;
}
struct Node
{
    int p, d;
    int id;
    Node() {}
    Node(int p, int d, int id) : p(p), d(d), id(id) {}
    bool operator<(const Node& rhs) const
    {
        return d > rhs.d || d == rhs.d && id < rhs.id;
    }
};
int main()
{
    int n;
    scanf("%d", &n);
    ll inv = Pow(100);
    for (int i = 0; i < N; i++) bit[i] = 1;
    std::vector a(n);
    for (int i = 0; i < n; i++)
    {
        scanf("%d%d", &a[i].p, &a[i].d);
        a[i].id = i + 1;
    }
    std::sort(a.begin(), a.end());
    ll ans = 0;
    for (auto& t : a)
    {
        ll tmp = (query(t.id - 1) * ((inv * t.p) % mod)) % mod;
        (ans += tmp) %= mod;
        update(t.id, inv * (100 - t.p) % mod);
    }
    printf("%lld\n", ans);
    return 0;
}
全部评论

相关推荐

10-25 12:05
已编辑
湖南科技大学 Java
若梦难了:我有你这简历,已经大厂乱杀了
点赞 评论 收藏
分享
11-15 17:19
湖南大学 Java
成果成果成果果:这是哪个公司的hr,这么离谱吗,我没见过用性别卡技术岗的,身边女性同学拿大厂offer的比比皆是
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务