noshi91のメモ

データ構造のある風景

ABC339-F Product Equality の確率を保証する

 \lbrack 10 ^ 9 , 2 \times 10 ^ 9 \rbrack から一様ランダムに素数  P を選ぶ *1 A _ i A _ j \neq A _ k となる  1 組の  ( i , j , k ) を固定し、誤判定する、すなわち  A _ i A _ j \equiv A _ k \pmod P となる確率を求める。 これは  A _ i A _ j - A _ k P で割り切れることと同値である。

 \lbrack 10 ^ 9 , 2 \times 10 ^ 9 \rbrack の範囲に素数 47374753 個存在する *2 。 一方、 0 \lt \lvert A _ i A _ j - A _ k \rvert \leq 10 ^ { 2000 } であるから、 A _ i A _ j - A _ k は範囲内の素因数を  222 個以下しか持たない。 よって一様ランダムに選んだとき、誤判定の確率は  222 / 47374753 \leq 10 ^ { - 5 } 以下である。

 4 つの素数を一様ランダムかつ独立に選ぶと、全ての素数で同時に誤判定する確率は  \left ( 10 ^ { - 5 } \right ) ^ 4 = 10 ^ { - 20 } 以下である。 独立に選ぶ部分が重要で、独立な事象が同時に発生する確率はその積となるという性質を用いて確率を抑えている。

 1 つのケースで最大  N ^ 3 \leq 10 ^ 9 組の  ( i , j , k ) に対して判定を行うので、 1 回以上誤判定する確率は  10 ^ { - 20 } \times 10 ^ 9 = 10 ^ { - 11 } 以下である。 この部分は union bound ( Boole's inequality - Wikipedia ) と呼ばれる直感的にはほとんど明らかな不等式を用いた。 この  N ^ 3 組では同じ  P を使っているため、これらの事象は独立ではない。 よって  1 - \left ( 1 - 10 ^ { - 20 } \right ) ^ {10 ^ 9} と計算するのは誤りである

テストケース間では  P を取り直すのでそれぞれは独立となるが、独立性を気にせず union bound を使った方が簡単になる。 全体で  1000 ケースある場合、 1 ケース以上 WA となる確率は  10 ^ { - 11} \times 1000 = 10 ^ {- 8} 以下である。  1000 ケースという想定が甘いかどうかと、 10 ^ {- 8 } という確率が許容可能かどうかは各自で判断するしかない。 人生が終わるまでにジャッジできる量、宇宙線アルゴリズムが破損するより低い確率、などで無理やり上限を付けることはできるかもしれない。

(おまけ) 乱択に工夫をするときに気を付けること

本問で独立に素数を選んだ部分で、既に選んだ素数を選ばないようにするという工夫が考えられる。 同じ素数を選ぶことは得にならないのでこれは改善になっているが、十分多い候補から素数を選ばなくてはならない都合上、同じ素数を選ぶ確率自体がとてつもなく小さいため効果が無視できるほどしかない。

また、乱択繋がりで rolling hash の基数に原始根を選ぶという工夫がある。 ランダムケースに対しては改善になっているかもしれないものの、もし作問者が参加者のそのような考えを見抜いて原始根を集中的に落とすケースを用意した場合は改悪となる *3

工夫によりアルゴリズムの挙動が複雑になると、確率の証明を付けることが難しくなりやすい。 そもそも証明により安全性が保障されたシンプルなアルゴリズムがあるのだから、それをそのまま使えばよい。

*1: 範囲内から一様ランダムに整数を選び、素数判定することを繰り返す

*2: WolframAlpha に PrimePi[2*109]-PrimePi[109-1] と入力する

*3: 乱数の出目は作問者には想定のしようがないことに注意