题解:细节真的坑……
考虑从左到右计算以每个点为右端点的区间的期望值,因为总共有个区间所以拉出去之后除一下就好。设f[i]是我们要求的东西(即期望值的分子),s[i]是第i位的数上一次出现在哪里,那么f[i]由三部分组成:对于当前位,贡献显然就是1(它本身),对于s[i]+1到i-1的部分,f[i]的这一部分是f[i-1]的这一部分分别+1(多了一个不同的数字),那么一共是i-1-s[i],对于s[i]之前的,因为有了相同的数字,所以就是f[i-1]的对应部分。所以得到以下递推式:
然后答案就是所有f[i]求和之后除以。
但是直接这么写的话一大堆地方会超出变量可以存储的数据范围……所以类型转换烦的一批……
代码如下:
#include<bits/stdc++.h>
using namespace std;
int n;
int a[1000010],f1[1000010],f2[1000010];
double f[1000010];
double ans;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++){scanf("%d",&a[i]);f2[i]=f1[a[i]];f1[a[i]]=i;}
for(int i=1;i<=n;i++)
{
f[i]=f[i-1]+(double)((i-f2[i])*2)/((double)n*(double)n);
ans+=f[i]-1.0/((double)n*(double)n);
}
cout<<ans<<endl;
return 0;
}