考虑期望的线性性,总期望视线长度等于每个人有每个视线长度的概率乘以视线长度的和,枚举每个人所在的位置和视线长度,计算满足这个人在这个位置有这个区间长度的排列个数然后除以n的阶乘,作和即可
计算排列个数用排列数和各种阶乘什么的搞一下就可以了,具体可以看代码里的注释部分
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<ctime> #include<cmath> #include<algorithm> #include<iomanip> #include<vector> #include<map> #include<set> #include<bitset> #include<queue> #include<stack> using namespace std; #define MAXN 1010 #define MAXM 1010 #define INF 1000000000 #define MOD 1000000007 #define eps 1e-8 #define ll long long int n; int a[MAXN]; int s[MAXN],b[MAXN]; int cnt[MAXN]; double ans; int t[MAXN]; int main(){ int i,j,k,l; scanf("%d",&n); for(i=1;i<=n;i++){ scanf("%d",&a[i]); } for(i=1;i<=n;i++){ b[i]=-1; for(j=1;j<=n;j++){ s[i]+=a[j]<a[i]; b[i]+=a[j]>=a[i]; } } for(i=1;i<=n;i++){ memset(cnt,0,sizeof(cnt)); for(j=1;j<=n;j++){ for(k=1;k<j&&k-1<=s[i];k++){ cnt[k]++; } if(j-1<=s[i]){ memset(t,0,sizeof(t)); for(l=2;l<=s[i];l++){ t[l]++; } for(l=2;l<=s[i]-(j-1);l++){ t[l]--; } for(l=2;l<=n-j;l++){ t[l]++; } for(l=2;l<=n;l++){ t[l]--; } double re=j; for(l=1;l<=n;l++){ while(t[l]>0){ re*=l; t[l]--; } while(t[l]<0){ re/=l; t[l]++; } } ans+=re; //ans+=P(s[i],j-1)*j*fac[n-j]/fac[n]; } } for(k=1;k-1<=s[i];k++){ memset(t,0,sizeof(t)); for(l=2;l<=s[i];l++){ t[l]++; } for(l=2;l<=s[i]-(k-1);l++){ t[l]--; } for(l=2;l<=n-k-1;l++){ t[l]++; } for(l=2;l<=n;l++){ t[l]--; } double re=1.0*cnt[k]*b[i]*k; for(l=1;l<=n;l++){ while(t[l]>0){ re*=l; t[l]--; } while(t[l]<0){ re/=l; t[l]++; } } ans+=re; //ans+=cnt[k]*P(s[i],k-1)*b[i]*k*fac[n-k-1]/fac[n]; } } printf("%.2lf\n",ans); return 0; } /* 3 1 2 3 */
