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;
}
相關文章
相關標籤/搜索