Codeforces 846F

原题链接: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

原文地址:https://www.cnblogs.com/MasterSpark/p/7529234.html