ferinの競プロ帳

競プロについてのメモ

Codeforces Round #641 (Div. 1) A. Orac and LCM

問題ページ

gcdを求めたいので素因数ごとに独立に考えて、最後に掛け合わせても問題ない。

例えば数列が (2^0, 2^1, 2^2, 2^3) であったとする。このときのlcmの集合は

  • \text{lcm}(2^0, 2^1) = 2^{\max(0, 1)}
  • \text{lcm}(2^0, 2^2) = 2^{\max(0, 2)}
  • \text{lcm}(2^0, 2^3) = 2^{\max(0, 3)}
  • \text{lcm}(2^1, 2^2) = 2^{\max(1, 2)}
  • \text{lcm}(2^2, 2^3) = 2^{\max(2, 3)}

となる。このときの \gcd2^{\max(0, 1)} となる。このように指数が小さい方から2番目の値のものが \gcd の指数となる。

あとは素因数ごとに指数が小さい方から2番目のものを列挙していく。指数が0のものもすべて列挙すると O(n \times (素数の個数)) かかってしまうので、各数の素因数のみを参照するように工夫する。

\text{num} \lbrack i \rbrack  = (素因数iを約数にもつ数の個数)\text{mi} \lbrack i \rbrack  = (素因数iの指数の最小)\text{mi2} \lbrack i \rbrack  = (素因数iの指数の小さい方から2番目) とした配列を持つ。数 A_i素因数分解を行い、現れた素因数についてこれらの配列の更新を行う。これは O(\sqrt{A_i}) でできる。

配列を構成した後、\text{num} \lbrack i \rbrack  = n であれば i^{\text{mi2} \lbrack i \rbrack } を答えに掛け、\text{num} \lbrack i \rbrack  = n-1 であれば i^{\text{mi} \lbrack i \rbrack } (最小の指数は0なので)を答えに掛ける。\text{num} \lbrack i \rbrack  \leq n-2 のときは2番目から小さい方の指数は0なので何もしなくても問題ない。

\text{num} \lbrack i \rbrack  = n-1 のときに i^{\text{mi2} \lbrack i \rbrack } を掛けてシステス落とした…