[BZOJ2720 Violet 5]列队春游(概率期望+组合数学)

列队春游

问题描述

输入格式:

输出格式:

样例输入:

3
1 2 3

样例输出:

4.33

提示

思路

根据期望的线性性质,我们可以枚举每种可能的视野,然后求和

对于每种视野,其期望为该种视野的视野长度 * 该种视野的概率

设某个小朋友的视野期望为 \(ans\) ,她的视野长度为 \(L\)

由于前面的第 \(i\) 个人如果被看到就会对答案有 \(1\) 的贡献,那么我们只要考虑前面的第 \(i\) 个人会被看到的概率就可以了,可以直接求和

\[ans = \sum_{i=1}^{n}i \times P(L \geq i) \]

设不小于第\(i\)个小朋友身高的有\(k\)个人(不包括他自己)

那么会挡住小朋友的人包括自己随便放总共有 \(A^{k+1}_n\) 种情况,其中那些会挡住小朋友的人不能放在小朋友前面的 \(i - 1\) 个位置,也不能放在小朋友的位置,所以方案数为 \(A^k_{n-i}\) ,然后又因为小朋友自己有 \(n-i+1\) 个位置可以放,所以乘上一个 \(n-i+1\)

所以最终

\[ans = \sum_{i=1}^{n} \frac{(n-i+1)A_{n-i}^{k}}{A_{n}^{k+1}} \]

然后就是 愉快的 导管子 导式子时光了

\[ans = \sum_{i=1}^{n}\frac{(n-i+1) \frac{(n-i)!}{(n-i-k)!}}{\frac{n!}{(n-k-1)!}} \]

\[ans = \frac{(n-k-1)!}{n!} \sum_{i=1}^{n}\frac{(n-i+1)!}{(n-i-k)!} \]

\[ans = \frac{(n-k-1)!}{n!}(k+1)! \sum_{i=1}^{n}\frac{(n-i+1)!}{(n-i-k)!(k+1)!} \]

\[ans = \frac{(n-k-1)!}{n!}(k+1)! \sum_{i=1}^{n}C_{n-i+1}^{k+1} \]

\[ans = \frac{(n-k-1)!}{n!}(k+1)! C_{n+1}^{k+2} \]

\[ans = \frac{n+1}{k+2} \]

很多题解都没有解释倒数第二个式子是怎么导出来的(可能只有我这个蒟蒻看不懂吧 大悲
简单解释一下:
先将 $ \sum $ 展开一下,得到

\[ans = \frac{(n-k-1)!}{n!}(k+1)! (C_{n-1+1}^{k+1}+C_{n-2+1}^{k+1}+...+C_{2}^{k+1}+C_{1}^{k+1}) \]

在式子最后加上一个 \(C_{1}^{k+2}\) (由定义可知\(C_{1}^{k+2}=0\)),得

\[ans = \frac{(n-k-1)!}{n!}(k+1)! (C_{n-1+1}^{k+1}+C_{n-2+1}^{k+1}+...+C_{2}^{k+1}+C_{1}^{k+1}+C_{1}^{k+2}) \]

由组合数递推式子 \(C_{n}^{m} = C_{n - 1}^{m - 1} + C_{n - 1}^{m}\) 将最后两项合并可得

\[ans = \frac{(n-k-1)!}{n!}(k+1)! (C_{n-1+1}^{k+1}+C_{n-2+1}^{k+1}+...+C_{2}^{k+1}+C_{2}^{k+2}) \]

反复合并,最终得到

\[ans = \frac{(n-k-1)!}{n!}(k+1)! C_{n+1}^{k+2} \]

code

Elaina's code
#include<bits/stdc++.h>
using namespace std;
const double eps=1e-8;
const int N=5050;
#define int long long
#define inf 0x3f
#define INF 0x3f3f3f3f
#define mst(a,b) memset(a,b,sizeof(a))
#define re register
#define Elaina 0
#define lson (rt<<1)
#define rson (rt<<1|1)
inline int read(){
    int x=0,f=1;
    char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
    for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
    return x*f;
}

int n,a[N];
double h[N],ans=0,sum=0;

main(){
	n=read();
	for(int i=1;i<=n;i++){
		a[i]=read();
		h[a[i]]++;
	}
	
	for(int i=1;i<=1000;i++){
		ans+=1.0*h[i]*(n+1)/(n-sum+1);
		sum+=h[i];
	}
	printf("%.2lf",ans);
    return Elaina;
}

都看到这了,真的不点个赞吗(>ω<*)

posted @ 2024-05-29 11:23  Elaina_0  阅读(14)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end