C - Standings Editorial by kyopro_friends

誤差評価

double で落ちること

倍精度浮動小数点数の精度は2進53桁です。したがって、\(\epsilon< 2^{-53}\) であるとき、\(x\)\((1+\epsilon)x\) を倍精度浮動小数点数に変換したものは等しくなる可能性があります。(詳しい人向けの注釈:非正規化数などは考えません)

実際、異なる 2 数 \(\displaystyle\frac{165580141}{267914296},\frac{433494437}{701408733}\) を倍精度浮動小数点数に変換すると同じ値になることが確かめられます。したがって、この問題を倍精度浮動小数点数を用いて解くことはできません。

long double で通ること

AtCoderのC++におけるlong doubleは、仮数部が(ケチbitなしの)64bitの拡張倍精度浮動小数点数、すなわち精度は2進64桁です。したがって、\(\epsilon > 2^{-63}\) のとき、\(x\)\((1+\epsilon)x\) をlong doubleに変換したものが等しくなることはありません。(詳しい人向けの注釈:非正規化数などは考えません)

正の整数 \(A,B,C,D\) に対して \(\frac{A}{B}\neq\frac{C}{D}\) のとき、\(|\frac{A}{B}-\frac{C}{D}|=\frac{1}{BD}|AD-BC|\geq\frac{1}{BD}\) であることから、今回の制約では、異なる 2 数の比は \(1+ 2^{-62}\) 以上です。よってそのような 2 数をlong doubleに変換したとき同じ値になることはありません。

また、\(\frac{A}{B}\) をlong doubleで表す際には(普通の実装では)除算が一度だけ行われるため、倍精度浮動小数点数など同様にIEEEの「四則演算は正確である(要約)」という規格に従っていれば、等しい値がlong doubleに変換したとき異なる値になることもありません。

よって、long doubleを用いればこの問題を解くことができます。

10^20を掛けると通ること

上で述べた通り、異なる 2 数 \(\frac{A}{B},\frac{C}{D}\) の差の絶対値は \(\frac{1}{BD}\) 以上であることから、今回の制約では全体を \(10^{20}\) 倍すると、異なる 2 数の差は \(1\) より大きくなります。よってそのような \(2\) 数を整数で計算したとき同じ値になることはありません。(\(x-y\geq 1\Rightarrow \lfloor x\rfloor - \lfloor y \rfloor \geq 1\) であるため)

posted:
last update: