zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    C语言基础
    R安装包
    随笔
    计算机组成原理(三)--存储器的层次结构
    计算机组成原理(一)
    查找
    二叉树
    Mesos
    第三章 线性表
    第四章 栈与队列
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/9629778.html
Copyright © 2011-2022 走看看