题面
题解
设第 \(k\) 个女性的如意郎君列表长度为 \(len\) , 那么我们选择这其中第 \(i\) 位的概率是
\[
\displaystyle\begin{aligned}&p*(1-p)^{i - 1} *\sum_{j = 0}^{\infty}(1-p)^{j*len}\\=&\frac{p*(1-p))^{i-1}}{1-(1-p)^len}\end{aligned}
\]
把后面拿个等比数列求下和即可, 因为是无穷项, 所以 \((1-p)^\infty \to 0\), 直接扔了
发现这个东西可以树状数组维护, 没了
Code
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <vector> #include <cmath> const int N = 5e5 + 5; #define double long double using namespace std; int n, m; double t[N], p, ans; vector<int> g[N]; template < typename T > inline T read() { T x = 0, w = 1; char c = getchar(); while(c < '0' || c > '9') { if(c == '-') w = -1; c = getchar(); } while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * w; } void add(int x, double y) { for(int i = x; i <= n; i += (i & -i)) t[i] += y; } double query(int x) { double res = 0; for(int i = x; i > 0; i -= (i & -i)) res += t[i]; return res; } int main() { n = read <int> (), m = read <int> (), scanf("%Lf", &p); for(int u, v, i = 1; i <= m; i++) { u = read <int> (), v = read <int> (); g[u].push_back(v); } double tmp; for(int sz, i = 1; i <= n; i++) { sz = g[i].size(), sort(g[i].begin(), g[i].end()); tmp = p / (1 - pow(1.0 - p, sz)); for(int j = 0; j < sz; j++, tmp *= (1 - p)) ans += (query(n) - query(g[i][j])) * tmp, add(g[i][j], tmp); } printf("%.2Lf\n", ans); return 0; }
来源:https://www.cnblogs.com/ztlztl/p/12358670.html