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但愿你可以求得不稳定因素的指望个数(即平均数目),
从而进一步研究为何速配算法不能知足你们的需求。c++

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 1spa

Sample Output

0.89code


思路

直接考虑每一个男人的指望贡献就能够了对象

用树状数组来维护ip

直接把每一个男人的被选几率算出来统计答案开发

这东西推一下等比数列求和就能够了input

水题it

不过要卡精度,勇士请使用long double


#include<bits/stdc++.h>

using namespace std;

typedef long double lb;
const int N = 1e6 + 10;

int n, m;
lb bit[N], p;
vector<int> g[N];

lb fast_pow(lb a, int b) {
  lb res = 1.0;
  while (b) {
    if (b & 1) res *= a;
    b >>= 1;
    a *= a; 
  } 
  return res;
}

void add(int x, lb val) {
  while (x < N) {
    bit[x] += val;
    x += x & (-x);
  }
}

lb query(int x) {
  lb res = 0;
  while (x) {
    res += bit[x];
    x -= x & (-x);
  }
  return res;
}

lb query(int l, int r) {
  return query(r) - query(l - 1);
}

int main() {
  scanf("%d %d", &n, &m);
  scanf("%Lf", &p);
  for (int i = 1; i <= m; i++) {
    int u, v; scanf("%d %d", &u, &v);
    g[u].push_back(v);
  }
  for (int i = 1; i <= n; i++) {
    sort(g[i].begin(), g[i].end());
  }
  lb ans = 0.0;
  for (int i = 1; i <= n; i++) {
    int len = g[i].size();
    for (int j = 0; j < len; j++) {
      lb cur = p * fast_pow(1.0 - p, j) / (1.0 - fast_pow(1.0 - p, len));
      ans += query(g[i][j] + 1, m) * cur;
      add(g[i][j], cur);
    }
  }
  printf("%.2Lf", ans);
  return 0;
}
相关文章
相关标签/搜索