[JSOI2015][BZOJ4481] 非诚勿扰 - 概率,期望,树状数组

等比数列算概率,然后按顺序插,在树状数组里查一下。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
#include <cctype>

using std::min;
using std::max;
using std::swap;
using std::memset;
using std::vector;
using std::set;
using std::isdigit;
using std::pow;

const int maxn = 5e+5 + 5;

int n, m;
long double p;
set<int> tb[maxn];
long double ans, b[maxn];

void add(int x, long double c) {for(; x <= n; x += (x & -x)) b[x] += c;}
long double sum(int x) {long double ret = 0.0; for(; x; x -= (x & -x)) ret += b[x]; return ret;}

inline int rd()
{
    int x = 0; char c = getchar();
    while(!isdigit(c)) c = getchar();
    while(isdigit(c)) x = x * 10 + (c ^ 48), c = getchar();
    return x;
}

int main()
{
    scanf("%d%d", &n, &m);
    scanf("%Lf", &p);
    for(register int i = 1; i <= m; ++i)
    {
        int a = rd(), b = rd();
        tb[a].insert(b);
    }
    for(register int i = 1; i <= n; ++i)
    {
        int tot = 0, siz = tb[i].size();
        for(set<int>::iterator it = tb[i].begin(); it != tb[i].end(); ++it)
        {
            //ans += sum(m) - sum(*it);
            double ppm = p * pow(1 - p, tot) / (1.0 - pow(1 - p, siz));
            ans += ppm * (sum(m) - sum(*it));
            add(*it, ppm);
            tot++;
        }
    }
    printf("%.2Lf\n", ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/nishikino-curtis/p/9625389.html