Description
link
Solution
考虑对于每一个人算贡献。
令 P(i) 表示这个人视野距离为 i 的概率, Q(i) 表示视野距离不小于 i 的概率,令 k 表示能够阻拦这个人视野的人的个数(当然不包括当前人)。
那么贡献即为:
i=1∑ni×P(i)
把这个式子转化下为:
i=1∑nQ(i)
所以这时候只需要算出来 Q(i) 即可,那么:
Q(i)=n!(n−i+1)⋅An−k−1i−1⋅(n−i)!
这个式子中 (n−i+1) 表示当前人有 n−i+1 个位置可以选。
An−k−1i−1 表示当前人前面的 i−1 个位置只能由不能阻拦当前人视野的人来选,一共有 n−k−1 个人。
(n−i)! 就表示除了当前人和其前面的 i−1 人外,其他人全排列的方案数。
然后化简即可:
ans=i=1∑nn!(n−i+1)⋅An−k−1i−1⋅(n−i)!=i=1∑nn!(n−i+1)⋅(n−k−i)!(n−k−1)!⋅(n−i)!=n!(n−k−1)!⋅i=1∑n(n−k−1)!(n−i+1)!=n!(n−k−1)!⋅(k+1)!⋅i=1∑nCn−i+1k+1
然后考虑这样一个式子:
i=1∑nCik
这个式子的组合意义就是在 n+1 个不同元素中选取 k+1 个元素的方案数。这里相当于就是枚举选的元素中编号最大的,假设为 s,那么方案数就为 s=1∑n+1Cs−1k=i=1∑nCik=Cn+1k+1。
所以 i=1∑nCn−i+1k+1=Cn+1k+2.
那么:
ans===n!(n−k−1)!⋅(k+1)!⋅Cn+1k+2(k+1)!(n−k−1)!⋅(k+1)!⋅(k+2)!⋅(n−k−1)!(n+1)!k+2n+1
所以就可以线性求解了。
Code
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| #include <bits/stdc++.h>
#ifdef ORZXKR #include <debug.h> #else #define debug(...) 114514 #endif
using namespace std;
const int kMaxN = 305, kMaxA = 1005;
int n, x; int sum[kMaxA]; double ans;
int main() { cin >> n; for (int i = 1, x; i <= n; ++i) { cin >> x; ++sum[x]; } for (int i = 1; i <= 1000; ++i) { ans += sum[i] * (n + 1) * 1.0 / (n - sum[i - 1] + 1); sum[i] += sum[i - 1]; } cout << fixed << setprecision(2) << ans << endl; return 0; }
|