codeforces 846F Random Query

来源:互联网 发布:淘宝详情页html代码 编辑:程序博客网 时间:2024/05/29 14:20
F. Random Query
time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
You are given an array a consisting of n positive integers. You pick two integer numbers l and r from 1 to n, inclusive (numbers are picked randomly, equiprobably and independently). If l > r, then you swap values of l and r. You have to calculate the expected value 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 in chosen segment.

Your answer will be considered correct if its absolute or relative error doesn't exceed 10 - 4 — formally, the answer is correct 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

题意:给定一个序列a,求任意选择两个数L,R  求区间(L,R)  (L>R则交换)  中出现数的数的种类个数 的期望。

分析: 每一个数ai对答案的贡献值就是 作为ai他是在那些区间是第一次出现的 , 对于 一个数 ai 求 他对那些L,R是有贡献的。我们只要 求出 前一个值为ai的出现位置L[ai],则 他的贡献 有( i-L[ai] ) * ( n-i+1 )*2 - 1

#include <iostream>#include<stdio.h>#include<algorithm>#include<string.h>#include<time.h>#include<vector>const int maxn = 1e6;typedef long long ll;using namespace std;ll n;int a[maxn+5];int l[maxn+5];void solve(){   ll cnt;   double tot=0;   memset(l,0,sizeof(l));   for(int i=1;i<=n;i++)   {      cnt = (i-l[a[i]])*(n-i+1)*2-1;      tot+=cnt*1.0;      l[a[i]] = i;   }   double ans = tot*1.0/n/n;   printf("%.6lf\n",ans);}int main(){    while(~scanf("%I64d",&n))    {        for(int i=1;i<=n;i++)        {            scanf("%d",&a[i]);        }        solve();    }    return 0;}


原创粉丝点击