D e s c i r p t i o n Descirption Descirption
有两个队伍A和B,每个队伍都有n个人。这两支队伍之间进行n场1对1比赛,每一场都是由A中的一个选手与B中的一个选手对抗。同一个人不会参加多场比赛,每个人的对手都是随机而等概率的。例如A队有A1和A2两个人,B队有B1和B2两个人,那么 ( A 1 v s B 1 , A 2 v s B 2 ) (A1 vs B1,A2 vs B2) (A1vsB1,A2vsB2)和 ( A 1 v s B 2 , A 2 v s B 1 ) (A1 vs B2,A2 vs B1) (A1vsB2,A2vsB1)的概率都是均等的50%。
每个选手都有一个非负的实力值。如果实力值为X和Y的选手对抗,那么实力值较强的选手所在的队伍将会获得 ( X − Y ) 2 (X-Y)^2 (X−Y)2的得分。
求A的得分减B的得分的期望值。
数据范围: n ≤ 50000 n\leq 50000 n≤50000
S o l u t i o n Solution Solution
看到数据范围,自然先排个序总是好的
我们首先要求出 A A A能干掉 B B B中的哪些人,这样就可以辨认是加还是减
由于排了序,该过程直接二分(当然也可以用指针(因为是排了序了),这样就少一次 n l o g n nlogn nlogn)
在不考虑相遇概率的情况下,期望得分为:
∑ j = 1 r a n k ( a [ i ] − b [ j ] ) 2 − ∑ j = r a n k + 1 n ( a [ i ] − b [ j ] ) 2 \sum_{j=1}^{rank}(a[i]-b[j])^2-\sum_{j=rank+1}^{n}(a[i]-b[j])^2 ∑j=1rank(a[i]−b[j])2−∑j=rank+1n(a[i]−b[j])2
完全平方公式
= ∑ j = 1 r a n k ( a [ i ] 2 − 2 a [ i ] × b [ j ] + b [ j ] 2 ) − ∑ j = r a n k + 1 n ( a [ i ] 2 − 2 × a [ i ] × b [ j ] + b [ j ] 2 ) =\sum_{j=1}^{rank}(a[i]^2-2a[i]\times b[j]+b[j]^2)-\sum_{j=rank+1}^{n}(a[i]^2-2\times a[i]\times b[j]+b[j]^2) =∑j=1rank(a[i]2−2a[i]×b[j]+b[j]2)−∑j=rank+1n(a[i]2−2×a[i]×b[j]+b[j]2)
分配率( s s s表示 b b b的前缀和, f f f表示 b b b的前缀平方和)
= r a n k × a [ i ] 2 − 2 a [ i ] × s [ r a n k ] + f [ r a n k ] − ( ( n − r a n k ) a [ i ] 2 − 2 a [ i ] × ( s [ n ] − s [ r a n k ] ) + f [ n ] − f [ r a n k ] ) =rank\times a[i]^2-2a[i]\times s[rank]+f[rank]-((n-rank)a[i]^2-2a[i]\times(s[n]-s[rank])+f[n]-f[rank]) =rank×a[i]2−2a[i]×s[rank]+f[rank]−((n−rank)a[i]2−2a[i]×(s[n]−s[rank])+f[n]−f[rank])
去括号
=
r
a
n
k
×
a
[
i
]
2
−
2
a
[
i
]
×
s
[
r
a
n
k
]
+
f
[
r
a
n
k
]
−
(
n
−
r
a
n
k
)
a
[
i
]
2
+
2
a
[
i
]
×
(
s
[
n
]
−
s
[
r
a
n
k
]
)
−
f
[
n
]
+
f
[
r
a
n
k
]
=rank\times a[i]^2-2a[i]\times s[rank]+f[rank]-(n-rank)a[i]^2+2a[i]\times (s[n]-s[rank])-f[n]+f[rank]
=rank×a[i]2−2a[i]×s[rank]+f[rank]−(n−rank)a[i]2+2a[i]×(s[n]−s[rank])−f[n]+f[rank]
再考虑一下相遇的概率, x j b xjb xjb乱推可以发现就是 1 n \frac 1 n n1
然后就可以我靠( w o r k o u t work\ out work out)了
时间复杂度: O ( n l o g n + n l o g n ) O(nlogn+nlogn) O(nlogn+nlogn)(排序+二分), O ( n l o g n + n ) O(nlogn+n) O(nlogn+n)(排序+指针)
由于本人很菜,当然打的是二分啦(短啊)
C o d e Code Code
#include<cstdio>
#include<cctype>
#include<algorithm>
using namespace std;int n,rank;
long double ans,s[50001],f[50001],a[50001],b[50001];
signed main()
{
scanf("%d",&n);
for(register int i=1;i<=n;i++) scanf("%Lf",a+i);
for(register int i=1;i<=n;i++) scanf("%Lf",b+i);
sort(a+1,a+1+n);sort(b+1,b+1+n);
for(register int i=1;i<=n;i++) s[i]=s[i-1]+b[i],f[i]=f[i-1]+b[i]*b[i];//预处理
for(register int i=1;i<=n;i++)
{
rank=lower_bound(b+1,b+1+n,a[i])-(b+1);//二分找排名
ans+=rank*a[i]*a[i]-2*a[i]*s[rank]+f[rank];//加上A队得分
ans-=(n-rank)*a[i]*a[i]-2*a[i]*(s[n]-s[rank])+f[n]-f[rank];//减去B队得分
}
printf("%.1Lf",ans/1.0/n);//记得除以相遇的概率
}