zoukankan      html  css  js  c++  java
  • Bzoj4481 [Jsoi2015]非诚勿扰

    Time Limit: 20 Sec  Memory Limit: 512 MB
    Submit: 147  Solved: 75

    Description

    【故事背景】
    JYY赶上了互联网创业的大潮,为非常勿扰开发了最新的手机App实现单身大龄青年之间的“速配”。然而随着用户数量的增长,JYY发现现有速配的算法似乎很难满足大家的要求,因此JYY决定请你来调查一下其中的原因。
    【问题描述】
    应用的后台一共有N个女性和M个男性,他们每个人都希望能够找到自己的合适伴侣。为了方便,每个男性都被编上了1到N之间的一个号码,并且任意两个人的号码不一样。每个女性也被如此编号。

    JYY应用的最大特点是赋予女性较高的选择权,让每个女性指定自己的“如意郎君列表”。每个女性的如意郎君列表都是所有男性的一个子集,并且可能为空。如果列表非空,她们会在其中选择一个男性作为自己最终接受的对象。
    JYY用如下算法来为每个女性速配最终接受的男性:将“如意郎君列表”中的男性按照编号从小到大的顺序呈现给她。对于每次呈现,她将独立地以P的概率接受这个男性(换言之,会以1−P的概率拒绝这个男性)。如果她选择了拒绝,App就会呈现列表中下一个男性,以此类推。如果列表中所有的男性都已经呈现,那么中介所会重新按照列表的顺序来呈现这些男性,直到她接受了某个男性为止。
    显然,在这种规则下,每个女性只能选择接受一个男性,而一个男性可能被多个女性所接受。当然,也可能有部分男性不被任何一个女性接受。这样,每个女性就有了自己接受的男性(“如意郎君列表”为空的除外)。现在考虑任意两个不同的、如意郎君列表非空的女性a和b,如果a的编号比b的编号小,而a选择的男性的编号比b选择的编号大,那么女性a和女性b就叫做一对不稳定因素。
    由于每个女性选择的男性是有一定的随机性的,所以不稳定因素的数目也是有一定随机性的。JYY希望你能够求得不稳定因素的期望个数(即平均数目),从而进一步研究为什么速配算法不能满足大家的需求。

    Input

    输入第一行包含2个自然数N,M,表示有N个女性和N个男性,以及所有女
    性的“如意郎君列表”长度之和是M。
    接下来一行一个实数P,为女性接受男性的概率。
    接下来M行,每行包含两个整数a,b,表示男性b在女性a的“如意郎君列表”
    中。
    输入保证每个女性的“如意郎君列表”中的男性出现切仅出现一次。
    1≤N,M≤500,000,0.4≤P<0.6

    Output

    输出1行,包含一个实数,四舍五入后保留到小数点后2位,表示不稳定因素的期望数目。

    Sample Input

    5 5
    0.5
    5 1
    3 2
    2 2
    2 1
    3 1

    Sample Output

    0.89

    HINT

    Source

    数学问题 期望 脑洞题

    期望还能这么玩儿,真的神奇。

    女方如果选中某个人,可能是第一轮选中的,也可能是第一轮没选人,在第二轮选中的,也可能在第三轮,第四轮……

    看上去是个无限项的等比数列求和。

    利用等比数列公式计算女方选某个人的概率:

      $ frac{a_1*(1-p^n)}{1-p}$

    在n无穷大的时候$ p^n $趋近于0,可以直接忽视掉。

    这样就可以算出这个位置被选的概率。

    这样,之后开始选择的女方如果选了某个更靠前位置,就多了这么些概率贡献一个逆序对。

    将边按双关键字排序,用树状数组维护一个类似逆序对的东西即可。

    数据卡精度,需要long double

     1 /*by SilverN*/
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<cstdio>
     5 #include<cmath>
     6 #include<cstring>
     7 using namespace std;
     8 const int mxn=500010;
     9 int read(){
    10     int x=0,f=1;char ch=getchar();
    11     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    12     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
    13     return x*f;
    14 }
    15 struct edge{
    16     int x,y;
    17     bool operator < (const edge &b)const{
    18         return ((x==b.x && y<b.y) || x<b.x);
    19     }
    20 }a[mxn],c[mxn];
    21 //
    22 int n,m;
    23 int len[mxn];
    24 long double P,pr[mxn];
    25 long double t[mxn];
    26 void add(int x,double v){while(x<=n){t[x]+=v;x+=x&-x;}}
    27 long double ask(int x){double res=0.0;while(x){res+=t[x];x-=x&-x;}return res;};
    28 inline long double GetP(int x,int y){return P*pr[y-1]/(1-pr[len[x]]);}
    29 int main(){
    30 //    freopen("in.txt","r",stdin);
    31     n=read();m=read();scanf("%Lf",&P);
    32     pr[0]=1.0;
    33     for(int i=1;i<=m;i++){pr[i]=pr[i-1]*(1-P);}
    34     for(int i=1;i<=m;i++){
    35         a[i].x=read();a[i].y=read();len[a[i].x]++;
    36     }
    37     sort(a+1,a+m+1);
    38     long double ans=0.0;
    39     int hd=1;
    40     for(int i=1;i<=n;i++){//枚举左边
    41         if(a[hd].x!=i)continue;
    42         int cnt=0;
    43         while(a[hd].x==i){
    44             ++cnt;
    45             add(a[hd].y,GetP(i,cnt));
    46             ans+=GetP(i,cnt)*(ask(n)-ask(a[hd].y));
    47             hd++;
    48         }
    49     }
    50     printf("%.2f
    ",(double)ans);
    51     return 0;
    52 }
  • 相关阅读:
    读书笔记五
    读书笔记四
    读书笔记3(Teamwork)
    读书笔记二(合格的软件工程师)
    读书笔记1(软件 = 程序 + 工程)
    关于使用Java开发Mis系统
    课堂动手动脑
    Quartz学习
    把数据库中取出的DataTable转换成一个对象 或者对象列表
    SAE上使用cron定时发微博
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/6946847.html
Copyright © 2011-2022 走看看