比赛
Description
有两个队伍A和B,每个队伍都有n个人。这两支队伍之间进行n场1对1比赛,每一场都是由A中的一个选手与B中的一个选手对抗。同一个人不会参加多场比赛,每个人的对手都是随机而等概率的。例如A队有A1和A2两个人,B队有B1和B2两个人,那么(A1 vs B1,A2 vs B2)和(A1 vs B2,A2 vs B1)的概率都是均等的50%。
每个选手都有一个非负的实力值。如果实力值为X和Y的选手对抗,那么实力值较强的选手所在的队伍将会获得(X-Y)^2的得分。
求A的得分减B的得分的期望值。
Input
第一行一个数n表示两队的人数为n。
第二行n个整数,第i个数A[i]表示队伍A的第i个人的实力值。
第三行n个整数,第i个数B[i]表示队伍B的第i个人的实力值。
Output
输出仅包含一个实数表示A期望赢B多少分。答案保留到小数点后一位(注意精度)。
Sample Input
2
3 7
1 5
Sample Output
20.0
Hint
【数据规模】
对于30%的数据,n≤50。
对于100%的.据,n≤50000;A[i],B[i]≤50000。
首先考虑
暴力
把
拎出来,让他们两个人打,他们两个人会打
次
然后总方案数是
,所以答案是
把式子拆开来,
直接把
排序,对于每个
,二分在
数组里面找到位置,对于
维护它的前缀和,前缀平方和就好了
Code:
#include <bits/stdc++.h>
#define maxn 50010
#define LL long long
using namespace std;
LL a[maxn], n, sum[maxn], sum2[maxn];
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
int find(LL x){
int l = 1, r = n, ans = 0;
while (l <= r){
int mid = (l + r) >> 1;
if (a[mid] <= x) ans = mid, l = mid + 1; else r = mid - 1;
}
return ans;
}
int main(){
freopen("mat.in", "r", stdin);
freopen("mat.out", "w", stdout);
n = read();
for (int i = 1; i <= n; ++i) a[i] = read();
double ans = 0;
sort(a + 1, a + 1 + n);
for (int i = 1; i <= n; ++i) sum[i] = sum[i - 1] + a[i], sum2[i] = sum2[i - 1] + a[i] * a[i];
for (int i = 1; i <= n; ++i){
LL x = read();
if (x <= a[1]) ans += 1LL * n * x * x + sum2[n] - 2LL * x * sum[n];
else if (x >= a[n]) ans -= 1LL * n * x * x + sum2[n] - 2LL * x * sum[n];
else{
LL s = find(x);
ans += -(s * x * x + sum2[s] - 2LL * x * sum[s]) + 1LL * (n - s) * x * x + sum2[n] - sum2[s] - 2LL * x * (sum[n] - sum[s]);
}
}
/* for (int i = 1; i <= n; ++i){
LL x = read();
for (int i = 1; i <= n; ++i)
if (x <= a[i]) ans += (a[i] - x) * (a[i] - x);
else ans -= (x - a[i]) * (x - a[i]);
}*/
printf("%.1lf\n", 1.0 * ans / n);
return 0;
}