比赛 解题报告

比赛

题目描述

有两个队伍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的得分的期望值。

输入输出格式

输入格式:

第一行一个数n表示两队的人数为n。 第二行n个整数,第i个数A[i]表示队伍A的第i个人的实力值。 第三行n个整数,第i个数B[i]表示队伍B的第i个人的实力值。

输出格式:

输出仅包含一个实数表示A期望赢B多少分。答案保留到小数点后一位(注意精度)。

说明

对于30%的数据,n≤50。

对于100%的数据,n≤50000;A[i],B[i]≤50000。


昨天刚学期望今天就考了,喵喵喵

如果把\(b\)队看成位置,把\(a\)队的人往里面放,一共可以产生\(n!\)种情况。

则对任意的二元配对组\(A_i\)\(B_j\),它们产生的答案即为

\((A_i-B_i)*(n-1)!/n!\),乘上的\((n-1)!\)即为它的出现次数

则总答案为

\((\sum_{i=1}^{n} \sum_{j=1,A[i]>=B[j]}^{n} {(A[i]-B[j])}^2-\sum_{i=1}^{n} \sum_{j=1,A[i]<B[j]}^{n} {(A[i]-B[j])}^2)/n\)

将A,B两个数组排序,递推统计即可。把完全平方公式拆开多维护一点信息即可。

注意精度问题,此题输入全为整数,所以最后再转double


#include <cstdio>
#include <algorithm>
#include <cmath>
#define ld long long
const int N=50010;
int n,pos=0;
ld a[N],b[N],s1=0,s2=0,ans=0,sum1=0,sum2=0;
void init()
{
    std::sort(a+1,a+1+n);
    std::sort(b+1,b+1+n);
    while(pos<n&&a[1]>=b[pos+1]) pos++;
    for(int i=1;i<=pos;i++)
    {
        s1+=(a[1]-b[i])*(a[1]-b[i]);
        sum1+=b[i];
    }
    for(int i=n;i>pos;i--)
    {
        s2+=(b[i]-a[1])*(b[i]-a[1]);
        sum2+=b[i];
    }
    ans+=s1-s2;
}
void work()
{
    for(int i=2;i<=n;i++)
    {
        int las=pos+1;
        while(pos<n&&a[i]>=b[pos+1])
            pos++;
        for(int j=las;j<=pos;j++)
            sum2-=b[j];
        for(int j=las;j<=pos;j++)
        {
            s1+=(a[i]-b[j])*(a[i]-b[j]);
            s2-=(b[j]-a[i-1])*(b[j]-a[i-1]);
        }
        s1+=(a[i]-a[i-1])*((las-1)*(a[i]+a[i-1])-2*sum1);
        s2+=(a[i]-a[i-1])*((n-pos)*(a[i]+a[i-1])-2*sum2);
        ans+=s1-s2;
        for(int j=las;j<=pos;j++)
            sum1+=b[j];
    }
}
int main()
{
    //freopen("data.in","r",stdin);
    //freopen("zj.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%lld",a+i);
    for(int i=1;i<=n;i++)
        scanf("%lld",b+i);
    init();
    work();
    double out=double(ans)/double(n);
    printf("%.1lf\n",out);
    return 0;
}

2018.6.26

posted @ 2018-06-26 11:51  露迭月  阅读(194)  评论(0编辑  收藏  举报