总述
初始 rating 默认 1500,每场比赛后的 rating 只与赛前各参赛选手的 rating 和赛后排名有关。
打得越好,rating 越高。计算 rating 的方式是 Elo 积分。
步骤
(翻译自https://codeforces.com/blog/entry/20762)
rating 高代表实力高,应该比 rating 低的获胜(即排名靠前)概率大。
P
i
,
j
=
1
1
+
1
0
r
j
−
r
i
400
,
r
i
>
r
j
P_{i,j}=\frac{1}{ 1+10^{ \frac{r_j-r_i}{400} } } \quad, r_i>r_j
Pi,j=1+10400rj−ri1,ri>rj
上面公式中,
P
i
,
j
P_{i,j}
Pi,j 代表选手
i
i
i 与选手
j
j
j 相比获胜的概率,
i
i
i号选手的 rating 为
r
i
r_i
ri 。
由上面的公式,我们可以在赛前计算出每位选手的预期排名(不是简简单单的把 rating 排一遍,因为 rating 的排名无法反映 rating 的差距),即
s
e
e
d
seed
seed 。
s
e
e
d
i
=
1
+
∑
j
=
1
,
j
≠
i
n
P
j
,
i
seed_i = 1+\sum_{j=1,j\ne i}^{n}P_{j,i}
seedi=1+j=1,j=i∑nPj,i
比如 Round #318 (Div. 1) 赛前 Petr 的 rating 为 3029 ,
s
e
e
d
P
e
t
r
≈
10.7
seed_{Petr}\approx 10.7
seedPetr≈10.7,赛后 Petr 的排名为 9 ,十分接近。
选手 rating 就是以赛前预期排名和赛后真实排名为依据进行更新的。
在赛后得到真实排名 a i a_i ai 后,令 m i = s e e d i ⋅ a i m_i=\sqrt{seed_i \cdot a_i} mi=seedi⋅ai , m i m_i mi 可以理解为预期与真实排名相协调后的结果。我们二分出一个新的 rating 为 r i = R r_i=R ri=R,使得 s e e d i ′ = m i seed_i'=m_i seedi′=mi。 R R R 符合选手 i i i 的赛时水平。令 d i = R − r i 2 d_i=\frac{R-r_i}{2} di=2R−ri,这就是 r i r_i ri 的改变量。
但为了防止分数膨胀,我们引入
i
n
c
=
m
i
n
(
m
a
x
(
−
∑
1
n
d
i
n
,
−
10
)
,
0
)
inc=min(max(-\frac{\sum_{1}^{n} d_i}{n},-10),0)
inc=min(max(−n∑1ndi,−10),0)。这样最终 raing 的变化是:
r
i
=
r
i
+
d
i
+
i
n
c
r_i=r_i+d_i+inc
ri=ri+di+inc
这样计算出的结果满足下面两个性质:
- 若赛前 r A < r B r_A<r_B rA<rB,比赛结果 A 依然比 B 差,那么更新后 r A < = r B r_A<=r_B rA<=rB。
- 若赛前 r A < r B r_A<r_B rA<rB,比赛结果 A 比 B 要好,那么 rating 的改变量 A>=B。
后记
前面 P i , j P_{i,j} Pi,j 的式子是由正态分布公式积分后再用最小二乘法得到的,推导方法可见知乎上的一篇回答“通俗讲义:匹配系统核心 “ELO”积分揭秘”。
文章步骤部分翻译自 Open Codeforces Rating System,如有错误欢迎指出。