2019.3.8 提高B组 T2 JZOJ 3055 比赛

33 篇文章 0 订阅
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 (XY)2的得分。

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

数据范围: n ≤ 50000 n\leq 50000 n50000


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])2j=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]22a[i]×b[j]+b[j]2)j=rank+1n(a[i]22×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]22a[i]×s[rank]+f[rank]((nrank)a[i]22a[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]22a[i]×s[rank]+f[rank](nrank)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);//记得除以相遇的概率
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值