[Jzoj] 3055.比赛

题目大意

有两个队伍 A A B B ,每个队伍都有 n n 个人。

这两支队伍之间进行 n n 1 1 1 1 比赛,每一场都是由 A A 中的一个选手与 B B 中的一个选手对抗。同一个人不会参加多场比赛,每个人的对手都是随机而等概率的。

每个选手都有一个非负的实力值。如果实力值为 X X Y Y 的选手对抗,那么实力值较强的选手所在的队伍将会获得 ( X Y ) 2 (X-Y)^2 的得分。

A A 的得分减 B B 的得分的期望值。

题目解析

根据期望的和 = = 和的期望,只需把 A A 队每个人的期望得分减去 B B 队每个人的期望得分即为答案。

A A 队某人 X X 的期望得分为
在这里插入图片描述
(其中 y y B B 队中实力低于 X X 的人, P P 代表 X X Y Y 相遇的概率)。

显然任意两个人相遇的概率是相等的, = = 两人第一场相遇的概率 + + 两人第一场不相遇的概率 * 两人第二场相遇的概率 + + ……。

排序后只需枚举一个人 i i ,用一个指针指着另一 队中实力比 i i 弱的里面最强的人,维护实力值的前缀和,实力值平方的前缀和即可算出期望。

显然指针只可能向右移动,所以这一步是线性的。

代码

#include<bits/stdc++.h>
#define L long long
using namespace std;
L n,l,r,t,ans,z,y;
L a[50005],b[50005],q1[50005],q2[50005];
double s,x=1;
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++) x*=i;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=n;i++) cin>>b[i];
	sort(a+1,a+1+n);
	sort(b+1,b+1+n);
	for(int i=1;i<=n;i++)
	 q1[i]=q1[i-1]+b[i],q2[i]=q2[i-1]+(b[i]*b[i]);
	for(int i=1;i<=n;i++)
	{
	  while(a[i]>b[t]&&t<=n)
	   t++;
	  z=(t-1)*a[i]*a[i]+q2[t-1]-2*a[i]*q1[t-1];
	  y=(n-t+1)*a[i]*a[i]+q2[n]-q2[t-1]-2*a[i]*(q1[n]-q1[t-1]);
	  ans+=z-y;
	}
	s=ans;
	cout<<fixed<<setprecision(1)<<s/n;
}

猜你喜欢

转载自blog.csdn.net/weixin_43909855/article/details/88366489