链接:https://www.nowcoder.com/acm/contest/143/F
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K 64bit IO Format: %lld
题目描述
Kanade has
boxes , the i-th box has
probability to have an diamond of
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 .
Notice: If
%
%
,then we denote that
%
%
输入描述:
The first line has one integer
.
Then there are
lines. each line has two integers
and
.
输出描述:
Output the answer module 998244353
示例1
3
50 1
50 2
50 3
输出
499122178
备注:
思路:分别考虑每个箱子钻石的贡献。
对于某个箱子,若要和这个箱子里的钻石交换,那么位于这个箱子之前的且比当前钻石大的钻石都不能被拿到;而比当前钻石小的,拿到拿不到没有影响;在它后面的钻石对这次交换也没影响。这样你就必定会与当前的钻石交换。
于是我们可以求出能交换到
这个钻石的概率
,那么这个箱子对答案的贡献是
。
所以
可以用树状数组维护更新
#include<bits/stdc++.h>
using namespace std;
const int MAX=1e5+10;
const int MOD=998244353;
const long long INF=1e18;
typedef long long ll;
struct lenka
{
int p,w,id;
}a[MAX];
int cmp(const lenka &A,const lenka& B)
{
if(A.w==B.w)return A.id<B.id;
return A.w>B.w;
}
ll A[MAX];
void add(int x,int n,int y){while(x<=n){(A[x]*=y)%=MOD;x+=x&(-x);}}
ll ask(int x){ll ans=1;while(x){(ans*=A[x])%=MOD;x-=x&(-x);}return ans;}
int main()
{
int inv=828542813;//100的逆元
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
scanf("%d%d",&a[i].p,&a[i].w);
a[i].id=i;
}
sort(a+1,a+n+1,cmp); //按权值从大到小排序
for(int i=1;i<=n;i++)A[i]=1;
ll ans=0;
for(int i=1;i<=n;i++)
{
ans+=ask(a[i].id-1)*a[i].p%MOD*inv%MOD;//查询在它之前比它大的概率乘积
ans%=MOD;
add(a[i].id,n,1ll*(100-a[i].p)*inv%MOD);
}
cout<<ans<<endl;
return 0;
}