Processing math: 75%

ユニークビジョンプログラミングコンテスト2024 秋(AtCoder Beginner Contest 372)F,G問題メモ

F - Teleporting Takahashi 2

問題文

  • N 頂点 N+M 辺の単純有向グラフ G があります。
    • 頂点には 1 から N の番号が、辺には 1 から N+M までの番号がつけられています。
    • i (1iN) は頂点 i から頂点 i+1 へ張られています。(ただし、頂点 N+1 は頂点 1 とみなします。)
    • N+i (1iM) は頂点 Xi から頂点 Yi へ張られています。
  • 高橋君は頂点 1 にいます。各頂点において、高橋君はその頂点から有向辺が張られている頂点に移動することができます。
  • 高橋君がちょうど K 回移動する方法が何通りあるかを求めてください。
    • すなわち、長さ K+1 の 整数列 (v0,v1,,vK) であって、下記の 3 つの条件をすべて満たすものの個数を求めてください。
      • i=0,1,,K について、1viN
      • v0=1
      • i=1,2,,K について、頂点 vi1 から頂点 vi へ有向辺が張られている。
  • ただし、答えは非常に大きくなることがあるので、答えを 998244353 で割った余りを出力してください。

制約

  • 2N2×105
  • 0M50
  • 1K2×105
  • 1Xi,YiN,XiYi
  • N+M 本の有向辺はすべて異なる
  • 入力は全て整数

解法

辺は、123...N1 をぐるっと一周する辺と、M 本の特殊辺からなる。特殊辺はとても少ない。

グラフ G から「特殊辺の端点になっていない、かつ①でない」頂点は縮約し、コスト付きのグラフ H に変えてしまう。

これを             こうじゃ
(G)                (H)  1
    ①-→②          ①-→②
  ↗  \ /  ↘       ↑1\ /1|
⑥     X     ③    2|  X  |2
  ↖ ↙ ↘ ↙       |↙ ↘↓
    ⑤←-④          ⑤←-④
                        1

グラフ H の頂点数は、多くとも 2M+1101 個である。
これなら、以下のDPをおこなえる。

  • DP[i,j]= ①を出発してコストがちょうど i で頂点 j にいるような経路の個数

状態数が O(KM)、遷移も i ごとに M 回なので O(KM) で、十分小さい。

全て埋め終わったら、答えとなる箇所を足していく。
この時、G から縮約した頂点で終わる経路も足し合わせる必要がある。

例えば②の場合、以下の2つが答えに寄与する。

  • コスト K で②に着く経路 DP[K,2]
  • コスト K で③に着く経路は、K1 で②に着く経路と1対1対応する。DP[K1,2]

H の頂点集合を VHVH の頂点 v に対し、時計回りで次の頂点までのコストを Cv として、

  • vVHk=0min

が答えとなる。

Python3

G - Ax + By < C

問題文

  • 長さ N の正整数列 A=(A_1,A_2,\ldots,A_N),B=(B_1,B_2,\ldots,B_N),C=(C_1,C_2,\ldots,C_N) が与えられます。
  • 以下の条件を満たす正整数の組 (x,y) の個数を求めてください。
    • 全ての 1\le i\le N に対して A_i\times x+B_i\times y \lt C_i が成立する。
  • なお、条件を満たす正整数の組の個数は有限個であることが証明できます。
  • T 個のテストケースが与えられるので、それぞれに対して答えを求めてください。

制約

  • 1\le T\le 2\times 10^5
  • 1\le N\le 2\times 10^5
  • 1\le A_i,B_i,C_i\le 10^9
  • 全てのテストケースにおける N の総和は 2\times 10^5 以下である
  • 入力は全て整数

解法

条件は y \lt \dfrac{-A_i x+C_i}{B_i} と言い換えられる。
制約から、傾きは負、切片は正であり、ゼロ除算の心配は無い。

このような直線群のどれよりも下にある、(x,y) が互いに正の格子点の個数を数えればよい。

y^
 |  \
 |~~--_x   \
 | ・ ・\--\_
 | ・ ・  \ \~~--__
 | ・ ・ ・ \\
 | ・ ・ ・ ・ x
 | ・ ・ ・ ・  \\
 | ・ ・ ・ ・ ・\
 +-----|-------|-------> x

以下の2段階の手順で解ける。

  • ConvexHullTrick の要領で、最小を取り得る直線と、そいつが最小となる区間を計算
  • 各区間に対し、FloorSum で答えを求める

やることは少し高度な典型の素直な組合せだが、注意すべき点が諸々あり、バグらせやすい。

  • 傾きや切片が有理数となるので、分子と分母で保持するなどして誤差を防ぐ。
  • 格子点のうち、x=0 または y=0 となる点や、直線上の点は含んではいけない。
    • 特に直線上の点について、素直なFloorSumは含んだ結果が求まるので、除く必要がある。
  • 単純にConvexHullTrickを適用した結果は、y \lt 0 となる範囲でしか最小とならない直線も含む。
    • 途中で次の直線との交点が y \le 0 になる直線になったらそこで打ち切る。
    • FloorSumも、最後の直線は「次の直線」ではなく「x 軸」との交点までの区間で求める。

Python3

programming_algorithm/contest_history/atcoder/2024/0921_abc372.txt · 最終更新: 2024/09/24 by ikatakos
CC Attribution 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0