mini notes

競技プログラミングの解法メモを残していきます。

ABC191F - GCD or MIN

問題:F - GCD or MIN

解答:Submission #20060874 - AtCoder Beginner Contest 191

解法:

「最終的に残る数」の構成

gcd(a, b) ≦ min(a, b) より、最終的に残る数はmin(A)以下である(以降min(A)をAminと呼ぶ)。また、あるAi1, Ai2, ..., Aixに対し、gcd(Ai1, Ai2, ..., Aix)はAmin以下であれば最終的に残る数の候補となりそうである。

実は最終的に残る数はAmin以下のgcd(Ai1, Ai2, ..., Aix)で構成される。X:最終的に残る数、Y:{gcd(Ai1, Ai2, ..., Aix), Amin以下}とし、X = Yであることを示す。

X⊂Yを示す。x∊Xに対し、A1, ..., ANの順列と、gcd or minの操作のN-1個の操作の選択が対応する。このときAisとAis+1に対し、gcdの操作が行われる場合はAisとAis+1をどちらも残し、minの操作が行われる場合は小さい方を残す作業を考える。この作業で最終的に残ったものにgcdの操作を行うと、その結果はxになり、かつx∊Yが言える。

Y⊂Xを示す。y∊Yに対し、以下の場合分けを考える。

  • gcdにAminが含まれている場合
    • gcdに現れない項とAminに対しminの操作を行い、その後Aminとgcdに現れる項に対しgcdを取る操作を行えば、これらの操作の結果はyになるため、y∊Xが言える。
  • gcdにAminが含まれていない場合
    • gcdに現れない項とAminに対しminの操作を行い、その後gcdに現れる項に対しgcdを取る操作を行い、最後にその結果とAminに対しminの操作を行えば、これらの操作の結果はyになるため、y∊Xが言える。

なお、gcd(Ai1, Ai2, ..., Aix)は単項のgcdをgcd(Ai) = Aiとして定義する。本問で最終的に残る数はAmin以下であり、単項gcdとしてはAminしか採用されない。

gcd(Ai1, Ai2, ..., Aix)の全探索

gcd(Ai1, Ai2, ..., Aix)の全探索は愚直にやると指数時間のオーダーが必要となる。実は次のような効率のよいアルゴリズムが存在する。

  • 各Aiの約数jに対し、変数tjを定義し、tj = Aiとする。既にtjが定義されている場合はtjをgcd(tj, Ai)に置き換える
  • i = 1, 2, ..., Nに対し上記の操作を行い、最終的にtj = jとなっているものがgcd(Ai1, Ai2, ..., Aix)によってあらわされる数となる

X:上記アルゴリズムで生成される数の集合、Y:gcd(Ai1, Ai2, ..., Aix)の集合とし、X = Yを示す。

X⊂Yを示す。x∊Xとする。最初にtxが定義されるときのAの項をAiとすると、xはAiの約数である。このときx=Aiであれば、x=gcd(Ai)でありx∊Yである。x<Aiのときはxの定義より、Aiとは別の項のAj1, ..., Ajtが存在し、x = gcd(Ai, Aj1, ..., Ajt)となっているはずである。よってこの場合もx∊Yである。

Y⊂Xを示す。y∊Yとする。

  • yがAの1つの項のAiのgcdであるとき
    y = gcd(Ai) = Aiである。このとき、tAiに対する上記アルゴリズムの操作と、それに対するtAiの挙動を確認する。
    • Aiより前の項の操作
      y | AgなるAgが存在したとすると、tAi = Agとして定義される。ただし、Ag以降にy | AhなるAhが1つでもあれば、tAi = gcd(Ag, Ah)となる。このとき、y' = gcd(Ag, Ah)とすると、gcdの性質よりy | y'である。
    • Aiの操作
      y | AgなるAgが存在したとき、tAiはy | y''なるy''を用いてtAi = y''と表せる。AiではtAi = gcd(y'', y) = yとなる。存在しなかったとき、tAi = yとして定義される。いずれの場合もtAi = yとなる。
    • Aiより後の項の操作
      y | AjなるAjではtAi = gcd(y, Aj) = yのままであるし、y | AjでないAjはtAiに影響を与えない。よって最終的にtAi = y = Aiとなる。
  • yが複数の項のgcdであるとき
    gcdに現れる項Aiに対してはy | y'なるy'が存在し、tAi = y'となる。また、gcdに現れる項の操作がすべて完了するとtAi = yとなる。gcdに現れない項Ajの操作については、y | AjであるAjではy | y'なるy'が存在し、tAj = y'となるし、y | AjでないAjはtAiに影響を与えない。よってこれも最終的にtAi = yとなる。