空降题目处(外网)
点我点我点我
空降题目处(内网)
点我点我点我
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多少分。答案保留到小数点后一位(注意精度)。
Solution
可理解为
A
不变,
但是这样是
O(N!)
的.与题意不符.
所以,我们可以将
B
排序,做它的前缀和
在
然后就是推公式.
求
A
队正分:
=(Ai−2AiB1+B1)+(Ai−2AiB2+B2)+⋯+(Ai−2AiBk−1+Bk−1)+(Ai−2AiBk+Bk)N
=(Ai∗k−2AiXj+Yj)N
求
A
队负分:
=(Ai−2AiBk+1+Bk+1)+(Ai−2AiBk+2+Bk+2)+⋯+(Ai−2AiBN−1+BN−1)+(Ai−2AiBN+BN)N
=(Ai∗(N−k)−2Ai(XN−Xj)+(YN−Yj))N
即:
Ans=∑Ni=1(Ai∗k−2AiXj+Yj)−(Ai∗(N−k)−2Ai(XN−Xj)+(YN−Yj))N
还有神奇的精度问题…
我都不想说话了…
自己调吧,我帮不了你…
头晕?歇菜了?见Code 滑稽
Code
C++
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
double ans,x[50001],y[50001],a[50001],b[50001];
int n,t,j=1;
int bs(int l,int r,double d);
int get(int x);
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
scanf("%lf",&a[i]);
for (int i=1;i<=n;i++)
scanf("%lf",&b[i]);
sort(b+1,b+n+1);
for (int i=1;i<=n;i++)
{
x[i]=x[i-1]+b[i];
y[i]=y[i-1]+b[i]*b[i];
}
for (int i=1;i<=n;i++)
{
t=get(i);
j=t;
ans+=(a[i]*a[i]*(double)(t)-2*a[i]*x[t]+y[t])*1000/n;
ans-=(a[i]*a[i]*(double)(n-t)-2*a[i]*(x[n]-x[t])+(y[n]-y[t]))*1000/n;
}
printf("%.1lf",ans/1000);
}
int bs(int l,int r,double d)
{
if (l>=r)
return l;
int m=(l+r)/2;
if (d<b[m+1])
return bs(l,m,d);
else
return bs(m+1,r,d);
}
int get(int x)
{
int value=0;
int l=1,r=n,mid;
while (l<=r)
{
mid=(l+r)/2;
if (b[mid]>a[x]) r=mid-1;
else {l=mid+1;value=mid;}
}
return(value);
}
Pascal
var
a,b,sq,pre:array[0..50000] of int64;
i,j,n:longint;
score_a,score_b:int64;
procedure qsort_a(l,r:longint);
var
i,j,mid:longint;
begin
i:=l;
j:=r;
mid:=a[(i+j) div 2];
repeat
while a[i]<mid do inc(i);
while a[j]>mid do dec(j);
if i<=j then
begin
a[0]:=a[i];
a[i]:=a[j];
a[j]:=a[0];
inc(i);
dec(j);
end;
until i>j;
if l<j then qsort_a(l,j);
if i<r then qsort_a(i,r);
end;
procedure qsort_b(l,r:longint);
var
i,j,mid:longint;
begin
i:=l;
j:=r;
mid:=b[(i+j) div 2];
repeat
while b[i]<mid do inc(i);
while b[j]>mid do dec(j);
if i<=j then
begin
b[0]:=b[i];
b[i]:=b[j];
b[j]:=b[0];
inc(i);
dec(j);
end;
until i>j;
if l<j then qsort_b(l,j);
if i<r then qsort_b(i,r);
end;
begin
readln(n);
for i:=1 to n do read(a[i]);
for i:=1 to n do read(b[i]);
qsort_a(1,n);
qsort_b(1,n);
sq[0]:=0;
for i:=1 to n do
sq[i]:=sq[i-1]+sqr(b[i]);
pre[0]:=0;
for i:=1 to n do
pre[i]:=pre[i-1]+b[i];
i:=1;
j:=0;
score_a:=0;
repeat
while (b[j+1]<a[i])and(j+1<=n) do inc(j);
score_a:=score_a+j*sqr(a[i])+sq[j]-2*a[i]*pre[j];
inc(i);
until i>n;
sq[0]:=0;
for i:=1 to n do
sq[i]:=sq[i-1]+sqr(a[i]);
pre[0]:=0;
for i:=1 to n do
pre[i]:=pre[i-1]+a[i];
i:=1;
j:=0;
score_b:=0;
repeat
while (a[j+1]<b[i])and(j+1<=n) do inc(j);
score_b:=score_b+j*sqr(b[i])+sq[j]-2*b[i]*pre[j];
inc(i);
until i>n;
writeln((score_a-score_b)/n:0:1);
end.