[2018牛客多校(第五場)] take (樹狀數組+概率)

題目鏈接

take

題目大意

一共有n個箱子, 第i 個箱子有p[i]% 的概率開出大小爲d[i] 的鑽石。 初始玩家手裏有一個size爲0的鑽石, 且手裏最多只能有一個鑽石, 如果當前開的箱子中得到的鑽石大於手中的鑽石, 則替換, 問最終替換次數的期望是多少。 最終對答案模998244353。

數據範圍

1n105
1p[i]100
1d[i]109

解題思路

題意是讓求交換鑽石次數的期望, 因爲根據期望的性質E(x+y)=E(x)+E(y) , 可以將問題轉換爲每個鑽石對次數期望的貢獻, 因爲每個鑽石最多隻能交換一次, 所以每個鑽石的貢獻就是這個鑽石被選中的概率 × 這個鑽石能貢獻的交換次數(1次), 也就是求每個鑽石被選中的概率和。
如果第i 個鑽石要被選中, 那麼前i1size 比他大的都不能出現, 其他小的無所謂, 所以對於第i 個鑽石對答案的貢獻就是p[i]×(j<i,d[j]>d[i])(100p[j]) .

所以每次需要求一個前綴乘積, 可以用樹狀數組或者線段樹解決。
因爲是維護乘積, 所以要將樹狀數組初始化爲1, 同時還需要考慮維護分數用逆元處理一下。

使用樹狀數組按照size大小從大到小排序, 那麼每次查詢的樹狀數組的前綴乘積都是比他大的數的乘積。

/********************************************
 *Author*        :ZZZZone
 *Created Time*  : 日  8/ 5 17:08:31 2018
 * Ended  Time*  : 日  8/ 5 17:28:23 2018
*********************************************/

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <stack>
using namespace std;
#define debug(x) std::cerr << #x << " = " << (x) << std::endl
typedef pair<int, int> PII;
typedef long long LL;
typedef unsigned long long ULL;

inline void OPEN(string s){
    freopen((s + ".in").c_str(), "r", stdin);
    freopen((s + ".out").c_str(), "w", stdout);
}

const int MAXN = 1e5;
const int Mod = 998244353;

struct Node{
    int p, sz, id;
    bool operator < (const Node& tmp) const{
        return sz > tmp.sz || (sz == tmp.sz && id < tmp.id);
    }
}a[MAXN+5];

LL bitsum[MAXN+5];
int n;

LL fast_pow(LL x, LL y){
    LL res = 1LL;
    while(y != 0){
        if(y & 1) res =(res * x) % Mod;
        y >>= 1;
        x = (x * x) % Mod;
    }
    return res;
}

inline int lowbit(int x){return (x & (-x)); }

inline void Add(int p, LL x){
    while(p <= n){
        bitsum[p] = (bitsum[p] * x) % Mod;
        p += lowbit(p);
    }
}

inline LL Sigma(LL p){
    LL res = 1LL;
    while(p){
        res = (res * bitsum[p]) % Mod;
        p -= lowbit(p);
    }
    return res;
}

void Init(){
    scanf("%d", &n);
    for(int i = 1; i <= n; i++){
        scanf("%d %d", &a[i].p, &a[i].sz);
        a[i].id = i;
    }
    sort(a + 1, a + 1 + n);
    for(int i = 0; i <= MAXN; i++) bitsum[i] = 1LL;
}

void Solve(){
    LL ans = 0LL ,inv = fast_pow(100LL, Mod - 2);
    for(int i = 1; i <= n; i++){
        LL tmp = Sigma(a[i].id-1) * (LL)a[i].p % Mod * inv % Mod;
        ans = (ans + tmp) % Mod;
        Add(a[i].id, inv * (100LL - (LL)a[i].p) % Mod);
    }
    printf("%lld\n", ans);
}

int main()
{
    Init();
    Solve();
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章