P r o b l e m \mathrm{Problem} Problem
- 给定长度为 n n n 的序列 a a a。您要随机地选取两个数 l , r ∈ [ 1 , n ] l,r\in [1,n] l,r∈[1,n],如果 l > r l>r l>r,则交换 l , r l,r l,r。求 a l ∼ a r a_l\sim a_r al∼ar 中不同数字个数的期望。
- 1 ≤ n ≤ 1 0 6 1\le n\le 10^6 1≤n≤106, 1 ≤ a i ≤ 1 0 6 1\le a_i\le 10^6 1≤ai≤106。答案被认为是正确的当且仅当 min ( ∣ x − y ∣ , ∣ x − y ∣ x ) ≤ 1 0 − 4 \min\left(|x-y|,\dfrac{|x-y|}{x}\right)\le 10^{-4} min(∣x−y∣,x∣x−y∣)≤10−4,其中 x x x 是标准答案, y y y 是您的答案。
S o l u t i o n \mathrm{Solution} Solution
我们现在转化为了求出每一种情况的权值和,最后除以 n 2 n^2 n2。
考虑如何计算这个序列,我们需要钦定做出贡献的数字为最先出现的数字。
这样我们就可以从贡献的角度来进行考虑,每一个数字被多少个区间包括。
我们令上一次出现同样数字的位置记为 p r e i pre_i prei,那么贡献是: ∑ i = 1 n 2 ( i − p r e a i ) ( n − i + 1 ) − n \sum_{i=1}^{n} 2(i-pre_{a_i})(n-i+1)-n i=1∑n2(i−preai)(n−i+1)−n
减掉 n n n 是因为相同位置的区间被计算了两次。
因此期望即为: ∑ i = 1 n 2 ( i − p r e a i ) ( n − i + 1 ) − n n 2 \frac{\sum_{i=1}^{n} 2(i-pre_{a_i})(n-i+1)-n}{n^2} n2∑i=1n2(i−preai)(n−i+1)−n
然后就是结论题惹…
C o d e \mathrm{Code} Code
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 3e6;
int n, ans(0);
int a[N], pre[N];
int read(void)
{
int s = 0, w = 0; char c = getchar();
while (!isdigit(c)) w |= c == '-', c = getchar();
while (isdigit(c)) s = s*10+c-48, c = getchar();
return w ? -s : s;
}
signed main(void)
{
n = read();
for (int i=1;i<=n;++i) a[i] = read();
for (int i=1;i<=n;++i)
{
ans += (i - pre[a[i]]) * (n - i + 1) * 2;
pre[a[i]] = i;
}
ans -= n, n = n * n;
printf("%.6lf\n", 1.0 * ans / n);
return 0;
}