C - Standings Editorial by Kiri8128

Python での実装例

Python での実装例をいくつか紹介します。

ソートのキーを渡す方法

公式解説 と同様に、ソートのキーを渡したい場合、 Python では cmp_to_key 関数を使うことで実装できます。

from functools import cmp_to_key
def cmp(a, b):
    x, y, i = a
    xx, yy, ii = b
    s = x * yy - y * xx
    return 1 if s > 0 else -1 if s < 0 else 0

N = int(input())
X = []
for i in range(N):
    a, b = map(int, input().split())
    X.append((-a, a + b, i))

X.sort(key = cmp_to_key(cmp))
print(*[i + 1 for x, y, i in X])

2 つの要素を比較する cmp 関数では、比較結果を 10-1 で返し、 sort 関数の key に入れる際には cmp_to_key(cmp) とします。

AC コード PyPy 3(cmp_to_key を使用)


精度を上げて比較する方法

多倍長整数を使う方法

普通に a / (a + b) をソートすると、浮動小数点数の精度が足りずに WA になってしまいます。

WA コード PyPy 3(浮動小数点数で比較)

Python では多倍長整数が扱えるので、十分な桁数を保持すれば良いです。例えば、 10 ** 100 を掛けて比較すると良いです。PyPy の場合タプルの比較は遅いことが知られているので、 (x, i) の代わりに x * 10 ** 6 + i などとして「一次元化」してソートする方法もあります。

AC コード PyPy 3(10 ** 100 を掛けて比較)

AC コード PyPy 3(10 ** 100 を掛けて比較、一次元化)


Decimal を使う方法

入力を Decimal で受け取ると浮動小数点数より精度を上げることができます。ただし Decimal は PyPy では遅くなるので TLE に注意です。

AC コード Python 3(精度 100 桁で Decimal を使用)

TLE コード PyPy 3(精度 100 桁で Decimal を使用)


\(10 ^ {18}\) 以下に埋め込む方法

\(\displaystyle \frac{a}{a+b}\) のソートは、逆数にして \(1\) を引くことで \(\displaystyle \frac{b}{a}\) のソートと等価になります。これにはいくつかの方法が知られていますが、商が \(1\) より大きいか小さいかで場合分けすることで、 \(0\le a,b \le 10^9 \) のとき、商を \(-10^{18}\) から \(10^{18}\) 程度の区間に(順序を保って)自然に埋め込むことができます。なお、途中計算で \(O(N)\) 回程度 \(10^{18}\) を超える整数を扱う必要がありますが、比較の際には \(64\) bit に収まっているので、実行時間のボトルネックにはなりづらいです。 詳細は ngtkana さんのブログ の「行列式ではなく傾きを使う方法」にまとめて頂いたので参考にしてください。

AC コード PyPy 3 (\(10^{18}\) 以下に埋め込む方法)

posted:
last update: