F. Random Query
time limit per test 2seconds
memory limit per test 256megabytes
You are given an array a consisting of n positive integers. You pick twointeger numbers l and r from 1 to n, inclusive (numbers are picked randomly, equiprobably andindependently). If l > r, then you swap values of l and r. You have to calculate the expectedvalue of the number of unique elements in segment of the array from index l to index r, inclusive (1-indexed).
Input
The first line contains one integer number n(1 ≤ n ≤ 106). The second line contains n integer numbers a1, a2, ... an(1 ≤ ai ≤ 106) — elements of the array.
Output
Print one number — the expected number of unique elements inchosen segment.
Your answer will be considered correct if its absolute or relative error doesn'texceed 10 - 4 — formally, the answer iscorrect if , where x is jury's answer, and y is your answer.
Examples
Input
2
1 2
Output
1.500000
Input
2
2 2
Output
1.000000
【题意】
给出n个数,需要计算从1~n中选出两个数(可以相同)x,y,令l=min(x,y),r=max(x,y),区间[l,r]内不同数个数的期望值。
【思路】
显然期望值为所有情况(共n*n种)的不同数个数和,再除以情况数。
那么我们要做的便是在限制时间内算出所有情况的不同数个数和。
由于x,y的大小不确定,但是其实无论谁大谁小对结果的影响不大,所以我们先固定x<=y。
假设我们现在在考虑第i个数,且已经算出了前(i-1)个数所有区间的不同数个数。
-
如果它他前面没有与它相同的数,那么它的贡献为使每个区间都多一个数,即[1,i],[2,i],[3,i],[4,i]....[i,i],
-
如果它前面有与之相同的数,前一次出现的位置为pos,那么对于区间[1,i],[2,i]...[pos,i]来说不同数的个数并没有改变,当然剩下的区间由于之间不包括这个数,每个区间不同数的个数会加一。
由上面的分析,我们可以推出:假设前(i-1)个的所有区间(固定x<=y)不同数个数和为sum[i-1],那么前i个的所有区间(固定x<=y)不同数个数和为sum[i-1]+i-pre[i],其中pre[i]为第i个数前一次出现的位置(没有则为0)。
然后考虑x,y大小的任意性,每个数的贡献即为sum[i]*2-1,减一的原因为当x,y相等时只有一种情况。
于是扫一遍累加结果再除以情况数即可。
#include <cstdio>
#include <cmath>
#include <map>
#include <cstring>
#include <algorithm>
using namespace std;
#define mst(a,b) memset((a),(b),sizeof(a))
#define rush() int T;scanf("%d",&T);while(T--)
typedef long long ll;
const int maxn = 1000005;
const ll mod = 1e9+7;
const int INF = 0x3f3f3f3f;
const double eps = 1e-6;
int a[maxn],pre[maxn];
int main()
{
int n,x;
while(~scanf("%d",&n))
{
mst(pre,0);
ll ans=0;
ll temp=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&x);
temp+=i-pre[x];
pre[x]=i;
ans+=(ll)temp*2-1;
}
printf("%.6f\n",ans*1.0/n/n);
}
return 0;
}