题目:
有两个队伍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的得分的期望值。
分析:根据期望的和=和的期望,只需把A队每个人的期望得分减去B队每个人的期望得分即为答案。
A队某人X的期望得分为(其中y为B队中实力低于X的人,P代表X和Y相遇的概率)。
显然任意两个人相遇的概率是相等的,=两人第一场相遇的概率+两人第一场不相遇的概率*两人第二场相遇的概率+……。
30分做法:任意枚举两个人算期望。
100分做法:排序后只需枚举一个人i,用一个指针指着另一 队中实力比i弱的里面最强的人,维护实力值的前缀和,实力值平方的前缀和即可算出期望。
显然指针只可能向右移动,所以这一步是线性的。
附上代码:const
maxn=50000;
type
arr=array [0..maxn] of int64;
var
a,b,ans1,ans2:arr;
ans:extended;
n:longint;
procedure init;
var
i:longint;
begin
readln(n);
for i:=1 to n do
read(a[i]);
for i:=1 to n do
read(b[i]);
end;
procedure qsort(var temp:arr; l,r:longint);
var
i,j,k,mid:longint;
begin
i:=l; j:=r; mid:=temp[(l+r) div 2];
repeat
while temp[i]<mid do
inc(i);
while temp[j]>mid do
dec(j);
if i<=j then
begin
k:=temp[i];
temp[i]:=temp[j];
temp[j]:=k;
inc(i);
dec(j);
end;
until i>j;
if l<j then
qsort(temp,l,j);
if i<r then
qsort(temp,i,r);
end;
procedure main;
var
i,j:longint;
begin
qsort(a,1,n);
qsort(b,1,n);
for i:=1 to n do
begin
ans1[i]:=ans1[i-1]+b[i];
ans2[i]:=ans2[i-1]+b[i]*b[i];
end;
for i:=1 to n do
begin
while (j<n) and (a[i]>b[j+1]) do
inc(j);
ans:=ans+a[i]*a[i]*(2*j-n);
ans:=ans+2*ans2[j]-ans2[n];
ans:=ans-2*a[i]*(2*ans1[j]-ans1[n]);
end;
write(ans/n:0:1);
end;
begin
init;
main;
end.