链接:https://www.nowcoder.com/acm/contest/143/F
来源:牛客网
题目描述
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
看完别人写的代码发现这个题真的好简单。
整个解题思路就是一句话, 如果当前的盒子要有价值,那么他前边所有的盒子中可能出现比当前盒子钻石大的都不能出现钻石。 不好想的就是用树状数组去维护概率值。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=998244353;
const int N =1e5+5;
ll quick_pow(ll a,ll k)
{
ll ans=1;
while(k){
if(k&1) ans=ans*a%mod;
a=a*a%mod;
k>>=1;
}
return ans;
}
ll inv;// 100 的逆元
ll p[N],d[N];
ll g[N];
ll tmpd[N];
int n;
ll lowbit(ll x)
{
return x&(-x);
}
void update(ll x,ll val)
{
while(x>0){
g[x]=g[x]*val%mod;
x-=lowbit(x);
}
}
ll getsum(ll x)
{
ll ans=1;
while(x<N){
ans=ans*g[x]%mod;
x+=lowbit(x);
}
return ans;
}
int main()
{
inv=quick_pow(100,mod-2);
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%lld %lld",&p[i],&d[i]);
tmpd[i]=d[i];
}
int tot;
sort(tmpd+1,tmpd+n+1);
tot=unique(tmpd+1,tmpd+n+1)-(tmpd+1);
for(int i=1;i<N;i++) g[i]=1;
ll ans=0;
for(int i=1;i<=n;i++)
{
ll in=lower_bound(tmpd+1,tmpd+tot+1,d[i])-tmpd;
//cout<<"index "<<in<<endl;
ll res=getsum(in+1);
ans=(ans+ res*p[i]%mod*inv%mod)%mod;
update(in,(100-p[i])%mod*inv%mod);
}
cout<<ans<<endl;
return 0;
}