AtCoder Beginner Contest 482 E,F問題メモ

AtCoder Beginner Contest 482

今回、やけに制約見落としケアレスWAが多過ぎでダメダメ。

E - Diameter Endpoint Colors

問題文

  • $N$ 頂点の木 $T$ が与えられます。
    • $i=1,2,\dots,N-1$ について、$i$ 番目の辺は頂点 $u_i$ と頂点 $v_i$ を結んでいます。
    • 各頂点には色が塗られており、頂点 $v$ は色 $C_v$ で塗られています。
  • $1 \leq u \lt v \leq N$ を満たす整数組 $(u,v)$ で以下の条件を全て満たすものの個数を求めてください。
    • 頂点 $u$ と頂点 $v$ は同じ色で塗られている。
    • 頂点 $u$ と頂点 $v$ を結ぶ単純パスの長さは木 $T$ の直径と等しい。
  • ただしパスの長さはそのパスに含まれる辺の本数であり、木の直径はその木に含まれる任意の単純パスの長さの最大値です。

制約

  • $2 \leq N \leq 2 \times 10^5$
  • $1 \leq u_i, v_i \leq N$
  • 与えられるグラフは木をなす
  • $1 \leq C_i \leq N$
  • 入力は全て整数

解法

「木の直径・中心」を知っていますかという問題。これまでにもABCでいくつか類題は出題されている。

  • 木の中心:
    • 最も遠い頂点までの距離(離心数)が最小となる頂点。必ず1つまたは2つある。
  • 木の直径:
    • 木に存在する2頂点間の最大距離。必ず木の中心を通る。

木の中心が1個の場合

       ⓪
   ,--'|`--,
  ①   ②   ③
  :   :   :
  :  ⑥⑦  :
 ④⑤      ⑧⑨

中心⓪を根とした時の⓪に隣接する頂点(①②③)の部分木それぞれで、 最遠頂点までの距離と、最遠となる頂点集合をそれぞれ求める。

木の直径(中心が1個の場合は必ず偶数)の半分を $h$ として、⓪と最遠頂点との距離が $h$ 未満の部分木は除外。

$h$ である部分木だけ残し、異なる2つの部分木の最遠頂点から1つずつ選んだ同じ色の頂点ペアの個数が答え。

木の中心が2個の場合

こっちの方が楽。

  ①-----②
  :     :
  :     :
 ④⑤   ⑥⑦

2つの中心をそれぞれ根として部分木を1個の場合と同様に求める。
2つの部分木の最遠頂点から1つずつ選んだ同じ色の頂点ペアの個数が答え。

Python3

F - Mod M Divisor

問題文

  • 正整数 $N, M$ が与えられます。
  • $k = 0, 1, \dots, M-1$ について次の問題を解いてください。
    • 以下の条件を満たす正整数 $t$ が存在するかを判定してください。また、存在する場合は最小値を求めてください。
      • $N^t$ の正の約数 $x$ であって、$x \equiv k \pmod{M}$ となるものが存在する。

制約

  • $1 \leq N \leq 10^{14}$
  • $1 \leq M \leq 4 \times 10^5$
  • $N, M$ は整数

解法

$M=1$ の場合は明らかに $k=0$ に対して $t=1$ が答え。以下、$M \ge 2$ とする。

TLE 解法

$N$ の約数集合を $D=(d_1,d_2,...,d_k)$ とする。

以下の $M$ 頂点のグラフを考える。

  • 頂点に $0,1,...,M-1$ の番号が付いている。
  • 頂点 $v$ からは、$vd_1 \pmod{M}, vd_2 \pmod{M},..., vd_k \pmod{M}$ に有向辺がある。

この時、以下の $A=(A_0,...,A_{M-1})$ が答えとなる。

  • $A_{i}$ の値は、$D$ に属するいずれかの頂点から $i$ までの最短距離 $+1$
  • 到達不可能な場合は $A_{i}=-1$

だが、$10^{14}$ 以下の約数は最大 $\sigma=17280$ 個あるので、$O(\sigma M) \simeq 10^9$ となり間に合わない。

高速化

辺を約数集合 $D$ と対応づけると、 グラフの最短距離に直接結びつけてイメージしやすいのだが、辺の個数が増えてしまう。

その前段、素因数分解の結果に対応づけるだけで、高速化に繋がる。

$N$ の素因数分解を $P=(p_1,p_2,...,p_k)$ とする。 $N=12$ なら $P=(2,2,3)$ のように、同じ素因数も展開する。制約の範囲では $k \le 46$ 程度が保証される。

グラフの遷移を、大きな「フェーズ」と小さな「ステップ」に分ける。
フェーズが、TLE解法の1回の遷移「キュー内の各頂点から約数集合 $D$ の各辺で1回遷移する処理」に近く、 ステップが「その遷移を素因数ごとに分解して行う処理」となる。

  • フェーズ $i$ では、
    • 遷移元となる頂点集合を $Q_i$ とする。
      • フェーズ $1$ 開始時では $Q_1=\{1\}$ としておく。
    • フェーズ内の $j$ ステップ目では、
      • $Q_i$ の各頂点 $u$ につき、
        • $v=up_j \pmod{M}$ へ探索する。
        • この時、$A_v$ が未確定なら、$A_v=i$ で確定し、$Q_i$ に $v$ を追加する。
    • $Q_{i+1}$ を「フェーズ $i$ で新しく $Q_{i}$ に加えられた頂点」とし、次のフェーズへ。
  • $Q_{i}$ が空になったらフェーズのループを打ち切って終了。

こうすることで、$M$ 個の各頂点からの遷移が最大 $2k$ 程度に抑えられる。 (フェーズの最初の方に確定した頂点は、現フェーズ+次フェーズでそれぞれ約 $k$ の遷移が走る。最大 $k$ にすることも可)

AIに図化させた遷移図。用語が上記説明と違っていたり、ところどころ実線と点線が変な気がするが、まぁ言葉よりは断然わかりやすい。

Python3

programming_algorithm/contest_history/atcoder/2026/1031_abc482.txt · 最終更新: by ikatakos
CC Attribution 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0