bzoj4481非诚勿扰(期望dp)
Posted zh-comld
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj4481非诚勿扰(期望dp)相关的知识,希望对你有一定的参考价值。
有n个女性和n个男性。每个女性的如意郎君列表都是所有男性的一个子集,并且可能为空。如果列表非空,她们会在其中选择一个男性作为自己最终接受的对象。将“如意郎君列表”中的男性按照编号从小到大的顺序呈现给她。对于每次呈现,她将独立地以P的概率接受这个男性(换言之,会以1?P的概率拒绝这个男性)。如果她选择了拒绝,App就会呈现列表中下一个男性,以此类推。如果列表中所有的男性都已经呈现,那么会重新按照列表的顺序来呈现这些男性,直到她接受了某个男性为止。显然,在这种规则下,每个女性只能选择接受一个男性,而一个男性可能被多个女性所接受。当然,也可能有部分男性不被任何一个女性接受。这样,每个女性就有了自己接受的男性(“如意郎君列表”为空的除外)。现在考虑任意两个不同的、如意郎君列表非空的女性a和b,如果a的编号比b的编号小,而a选择的男性的编号比b选择的编号大,那么女性a和女性b就叫做一对不稳定因素。求得不稳定因素的期望个数(即平均数目)
Solution
此题要求期望的逆序对数,我们先分析每个男性在每个女性的选择中被选择的概率(图是网上抄来的)
等比数列求和一下
概率求出来了,我们就可以以男性编号为下标,维护一个树状数组,里面的值代表这个男性在前面出现的期望次数。
求出这个后,我们在乘上当前男性被选择的概率就可以成为答案的一部分。
Code
#include<iostream> #include<cstdio> #include<algorithm> #define N 500002 using namespace std; typedef long double ld; ld ans,tr[N],p; int n,m; struct zzh{ int x,y; }a[N]; bool cmp(zzh a,zzh b){ if(a.x!=b.x)return a.x<b.x; else return a.y<b.y; } void add(int x,ld y){while(x<=n)tr[x]+=y,x+=x&-x;} double query(int x){double ans=0;while(x)ans+=tr[x],x-=x&-x;return ans;} int main(){ // freopen("4481.in","r",stdin); // freopen("4481.out","w",stdout); scanf("%d%d%Lf",&n,&m,&p); for(int i=1;i<=m;++i)scanf("%d%d",&a[i].x,&a[i].y); sort(a+1,a+m+1,cmp); int now=1; for(int i=now;i<=m;i=now+1){ now=i; while(a[now].x==a[now+1].x)now++; ld x=1; for(int j=i;j<=now;++j)x*=(1-p);x=1-x; ld y=p; for(int j=i;j<=now;++j){ ld xx=y/x; add(n-a[j].y+1,xx); ans+=xx*query(n-a[j].y); y*=(1-p); } } printf("%.2Lf",ans); return 0; }
以上是关于bzoj4481非诚勿扰(期望dp)的主要内容,如果未能解决你的问题,请参考以下文章