题意:
好像没报名不能进,这边直接拉吧
就是给n个盒子,每个盒子有p[i]/100的概率开出siz[i]大小的钻石,开始的时候你手里的大小为0,如果开出比手里钻石大的话就交换,求的是交换次数的期望
解析:
对于i,对于答案的贡献的情况是:前面没拿比这个钻石大(或者相同)的钻石的概率*拿这个钻石的概况
这个想出来的话就异常简单了,用树状数组维护一下就行了
代码:
typedef long long D;
typedef double F;
const D mod=998244353;
const int N=100000;
D read(){ D ans=0; char last=' ',ch=getchar();
while(ch<'0' || ch>'9')last=ch,ch=getchar();
while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
if(last=='-')ans=-ans; return ans;
}
D swift(D a,D b){
D ans=1ll;
while(b){
if(b%2)ans=ans*a%mod;
b>>=1;
a=a*a%mod;
}return ans;
}
D inv(D a){return swift(a,mod-2);}
D a[100009];
const D inv100=inv(100);
struct node{
D p,s,id;
bool operator<(const node &a)const{
return s>a.s||s==a.s&&id<a.id;
}
}e[100009];
void add(D p,D v,D n){
while(p<=n){
a[p]=a[p]*v%mod;p+=p&(-p);
}
}
D q(D p){
D re=1;
while(p>0){
re=re*a[p]%mod,p-=p&(-p);
}return re;
}
int main(){
D n=read();
for(int i=0;i<=n;i++)a[i]=1;
for(int i=1;i<=n;i++){
scanf("%lld%lld",&e[i].p,&e[i].s);e[i].id=i;
}
D sum=0;
sort(e+1,e+1+n);
for(int i=1;i<=n;i++){
D tmp=q(e[i].id-1)*(e[i].p*inv100%mod)%mod;
sum=(sum+tmp)%mod;
add(e[i].id,(100-e[i].p)*inv100%mod,n);
}
printf("%lld\n",sum);
return 0;
}