链接: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
输出
499122178
备注:
1<= n <= 100000
1<=p[i]*100 <=100
1<=d[i]<=10^9
题意:有n个盒子,每个盒子出现大小为di的概率为pi,按id顺序遍历盒子,每次遇到比当前钻石大的就换掉,问更换次数期望。
要保证当出现第di个大小的钻石时能更换,那么说明在此之前比其大的钻石都没拿到,那么就是这个钻石之前的比其大的钻石没拿到的概率连乘,用树状数组维护这样失败概率的前缀积,并加上计算每个钻石如果更换的概率,乘上大小,即期望。
树状数组中存储第id个钻石没有di那么大的概率,那么,当在第id个位置更换成di那么大的钻石,就要保证在这之前的钻石都比di小
#include<bits/stdc++.h>
#define LL long long
#define M(a,b) memset(a,b,sizeof a)
#define pb(x) push_back(x)
#define lowbit(x) x&(-x)
using namespace std;
const int maxn=1e5+7;
const int p=998244353;
LL qp(LL a,LL b)
{
LL ans=1;
while(b)
{
if(b&1)ans=ans*a%p;
a=a*a%p;
b>>=1;
}
return ans;
}
struct node
{
LL val,id,pp;
bool operator <(const node &a)const
{
if(val==a.val)return id<a.id;
return val>a.val;
}
}a[maxn];
LL tre[maxn];
int n;
LL inv=qp(100,p-2);///注意题目给出的都是*100之后的概率,因此要*100的逆元才是真正的概率
void update(int pos,LL val)
{
for(int i=pos;i<=n;i+=lowbit(i))tre[i]=tre[i]*val%p;///树状数组计算前缀乘
}
LL query(int pos)
{
LL ans=1;
for(int i=pos;i;i-=lowbit(i))ans=ans*tre[i]%p;
return ans;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%lld%lld",&a[i].pp,&a[i].val),a[i].id=i;
sort(a+1,a+1+n);
fill_n(tre,n,1LL);///初始化全为1
LL ans=0;
for(int i=1;i<=n;i++)///按钻石从大到小的顺序更新树状数组,这样每次查询时都是查询该id之前,没有取得 小于自己id,且大小比自己大的钻石的概率
{
ans=(ans+query(a[i].id-1)*a[i].pp%p*inv%p)%p;///先查询比自己小的id的比自己大的钻石不取的概率
update(a[i].id,((LL)100-a[i].pp)*inv%p);///然后再更新取不到该钻石的概率到树状数组中
}
printf("%lld
",ans);
}