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

    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
     

     
    求出每个女性选择她的列表里的第x个男性的概率, 然后用树状数组维护一个类似逆序对的东西。
    思路很巧妙。
     

     
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    #define reg register 
    #define N 500005
    inline int read() {
        int res=0;char ch=getchar();
        while(!isdigit(ch))ch=getchar();
        while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
        return res;
    }
    
    int n, m;
    
    struct edge {
        int x, y;
    }ed[N];
    inline bool cmp(edge a, edge b) {
        if (a.x == b.x) return a.y < b.y;
        return a.x < b.x;
    }
    int hav[N];
    
    long double P, fac[N], ans = 0.0;
    
    long double tr[N];
    #define lowbit x & -x
    inline void add(int x, long double y) {
        while(x <= n) tr[x] += y, x += lowbit;
    }
    inline long double ask(int x) {
        long double res = 0.0;
        while(x) res += tr[x], x -= lowbit;
        return res;
    }
    
    int main()
    {
        n = read(), m = read();
        scanf("%Lf", &P);
        for (reg int i = 1 ; i <= m ; i ++)
        {
            int x = read(), y = read();
            ed[i].x = x, ed[i].y = y;
            hav[x]++;
        }
        sort(ed + 1, ed + 1 + m, cmp);
        int now = 1;
        fac[0] = 1;
        for (reg int i = 1 ; i <= m ; i ++) fac[i] = fac[i-1] * (1.0 - P);
        for (reg int i = 1 ; i <= n ; i ++) 
        {
            if (ed[now].x != i) continue;
            int cnt = 0;
            while(ed[now].x == i) {
                cnt++;
                long double pp = fac[cnt-1] * P / (1 - fac[hav[ed[now].x]]);
                add(ed[now].y, pp);
                ans += pp * (ask(n) - ask(ed[now].y));
                now++;
            }
        }
        
        printf("%.2lf
    ", (double)ans);
        return 0;
    }
  • 相关阅读:
    zabbix迁移思路
    top命令
    random随机数
    判断传入元素是否可见
    title_contains
    1.Selenium的工作原理以及网页上查找元素
    APP升级测试
    英语词汇
    作文 |素材笔记
    408计组 |二、数据的表示和运算
  • 原文地址:https://www.cnblogs.com/BriMon/p/9560900.html
Copyright © 2011-2022 走看看