题解 [Violet 5] 列队春游

传送门

不会 \(O(n)\) 做法……参考了这篇这篇题解才看懂

然而题解都很详细,所以我只解释一步,就是第三步
于是我们将一个方案定义为只考虑 \(k\) 个大于等于当前小朋友的人,剩下的人先不计入方案数
于是(只计算当前小朋友及能挡住他的人)方案数是 \(A_n^{k+1}\)
我们将这样的方案称作「基础方案」,而一个最终方案是将其余小朋友插入当前序列中得到的
于是考虑钦定这个小朋友的位置,有 \(n-i+1\) 种可能(\(i\) 是视野范围)
然后要钦定这个小朋友前面 \(i-1\) 个位置不能有能挡住他的人,于是乘上 \(A_{n-i}^k\)
后面的就按照题解的方法拆式子即可

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 310
#define ll long long
#define fir first
#define sec second
//#define int long long

char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
	int ans=0, f=1; char c=getchar();
	while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
	while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
	return ans*f;
}

int n;
double ans;
map<int, int> mp;

signed main()
{
	n=read();
	for (int i=1; i<=n; ++i) ++mp[read()];
	int cnt=0;
	for (auto it:mp) {
		int k=n-cnt-1;
		ans+=1.0*it.sec*(n+1)/(k+2);
		cnt+=it.sec;
	}
	printf("%.2lf\n", ans);

	return 0;
}
posted @ 2022-01-20 19:01  Administrator-09  阅读(4)  评论(0编辑  收藏  举报