题目链接
题目大意
一共有n个箱子, 第 i i 个箱子有的概率开出大小为 d[i] d [ i ] 的钻石。 初始玩家手里有一个size为0的钻石, 且手里最多只能有一个钻石, 如果当前开的箱子中得到的钻石大于手中的钻石, 则替换, 问最终替换次数的期望是多少。 最终对答案模998244353。
数据范围
1≤n≤105
1
≤
n
≤
10
5
1≤p[i]≤100
1
≤
p
[
i
]
≤
100
1≤d[i]≤109
1
≤
d
[
i
]
≤
10
9
解题思路
题意是让求交换钻石次数的期望, 因为根据期望的性质
E(x+y)=E(x)+E(y)
E
(
x
+
y
)
=
E
(
x
)
+
E
(
y
)
, 可以将问题转换为每个钻石对次数期望的贡献, 因为每个钻石最多只能交换一次, 所以每个钻石的贡献就是这个钻石被选中的概率
×
×
这个钻石能贡献的交换次数(1次), 也就是求每个钻石被选中的概率和。
如果第
i
i
个钻石要被选中, 那么前中
size
s
i
z
e
比他大的都不能出现, 其他小的无所谓, 所以对于第
i
i
个钻石对答案的贡献就是.
所以每次需要求一个前缀乘积, 可以用树状数组或者线段树解决。
因为是维护乘积, 所以要将树状数组初始化为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;
}