原题链接:http://codeforces.com/contest/846/problem/F
题意:给一个数列,任意取区间[l, r],问区间内不同数字的个数的期望是多少。
思路:
对于第i个数a[i],它对一些区间都有贡献,这区间一定是包含了这个数,那么假如数列中不存在相同的数,这些区间就是[1, i], [1, i+1], [1, i+2]...[1, n], [2, i]...[2, n]...[i, n],每个区间贡献度为1,这个数的贡献即为(n-i+1)*i*2(由于l,r存在顺序调换,需要乘2)
当数列中存在相同的数时,对于数a[i],前一个相同的数a[j]已经计算了它在包含前j个数的区间的贡献,这样我们只需要加上包含第 j 到 i 的数的贡献,标记a[i]的前一个位置为last[a[i]], 则贡献为 (n-i+1)*(n-last[ a[i] ])*2.
上述计算过程多计算了区间[l, l]的贡献,在最后减去n即可。
#include<iostream> #include<cstring> #include<cstdio> #include<iomanip> using namespace std; const int MAXN=1e6+10; int last[MAXN],num; int main() { int n; cin>>n; long long nu=0; memset(last, 0, sizeof(last)); for(int i=1;i<=n;i++) { scanf("%d", &num); nu+=1LL*(i-last[num])*(n-i+1); last[num]=i; } nu=nu*2-n; cout<<fixed<<nu*1.0/(n*1.0)/(n*1.0)<<endl; return 0; }
嗯,期望的题目可以通过计算每个元素的贡献度来做 :D