列队春游题解 O(n方)
题目
前言
出生镇楼
思路:
- 打个暴力先
#include<bits/stdc++.h>
#define int long long
using namespace std;
namespace Testify{
inline int read(){
int f(1),x(0);
char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
for(;isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+(ch^48);
return f*x;
}
inline void Write(int x){
if(x>9) Write(x/10);
putchar(x%10+48);
}
inline void write(int x){
if(x<0) putchar('-'),x=-x;
Write(x);
putchar('\n');
}
}
using namespace Testify;
const int N=305;
int n,tot(0);
int a[N];
double Tempestissimo(0);
signed main(void){
n=read();
a[0]=114514;
for(register int i=1;i<=n;i++){
a[i]=read();
}
sort(a+1,a+n+1);
do{
tot++;
Tempestissimo++;
for(register int i=2;i<=n;i++){
int cnt=0;
for(register int j=i-1;j>=0;j--){
cnt++;
if(a[j]>=a[i]){
break;
}
}
Tempestissimo+=cnt;
}
}while(next_permutation(a+1,a+n+1));
printf("%.2lf",Tempestissimo/tot);
return 0;
}
对于每种情况都模拟一遍最后加上然后除以总数\(tot\)即为答案
- 组合数学
对于每个小朋友都算出对应情况的方案数然后乘起来每个小朋友每种视野的期望就能得到答案
①预处理出对于每个小朋友 有多少身高比他矮的 小朋友 (注意一点身高和小朋友一样高的算比他高的,否则只能得50分) 假设\(h[i]\)表示对于第\(i\)个小朋友有多少身高比他矮的 小朋友
② 循坏枚举小朋友\(i\)和比小朋友身高低的忍术\(j\)
③ 对于每种比他矮的小朋友 (\(j+1\)即视野期望) 通过逆天 组合数学 得到答案
④ 组合数学从两方面考虑,一是第\(i\)个的小朋友前\(j+1\)个人 (即前面矮的j个人的前一个) 是身高比i大的小朋友
那么身高较矮的\(j\)个小朋友方案数为\(A_{h[i]}^j\)
从身高高或相等的小朋友抽取一个小朋友 方案数为\(A_{n-h[i]-1}^1\)
剩下的人随便放都可以,方案数\(A_{n-j-2}^{n-j-2}\)
将剩下\(n-j-2\)个人看做一个整体,将已经确定的\(j+2\)个人看做一个整体,那么就有\(n-j-1\)个空位插入\(1\)个整体,方案数为\((n-j-1)\)
⑤ 第二方面是第\(i\)个的小朋友前\(j+1\)个人 (即前面矮的j个人的前一个) 是老师
那么这种情况下 那么身高较 矮的\(j\)个小朋友方案数为\(A_{h[i]}^j\)
剩下的\(n-j-1\)个都是随便排,有方案数\(A_{n-j-1}^{n-j-1}\)种,
和上面不同的地方是,\(j+1\)个小朋友看做一个整体,这个整体一定在老师后面,即队伍最前面,就不能插空了
总结:设\(Tempestissimo\)为 总 的方案数,则
接下来在每次循环中都将 单独的 方案数乘上视野期望(即j+1)在累计到\(ans\)中即可!!!!!!
完结撒花!!不放代码捏
思路借鉴@Trump_