Upgrade to Pro — share decks privately, control downloads, hide ads and more …

第9回ゆるふわオンサイト_解説スライド.pdf

Avatar for forcia_dev_pr forcia_dev_pr
November 09, 2026
50

 第9回ゆるふわオンサイト_解説スライド.pdf

Avatar for forcia_dev_pr

forcia_dev_pr

November 09, 2026

More Decks by forcia_dev_pr

Transcript

  1. 目次 • 各問題FA・AC数 • writer/tester • A - Clear The

    Context • B - Miracle Dinner • C - Make Arithmetic Sequence • D - Tree Walking • E - Shinkansen • F - Maximum Zero Xor Prefixes • G - GCD Must Appear • H - I like carrying up • I - Hypercube Interior Paths 2
  2. 各問題のFA・AC数 問題 オンサイト FA 全体 FA AC数 A - Clear

    The Context edon8618 edon8618 45/45 B - Miracle Dinner edon8618 Kidodesu 45/45 C - Make Arithmetic Sequence anmichi yukimy32 39/43 D - Tree Walking anmichi potato167 37/37 E - Shinkansen binap Kude 3/9 F - Maximum Zero Xor Prefixes sounansya Kidodesu 8/19 G - GCD Must Appear - potato167 1/1 H - I like carrying up - - 0/0 I - Hypercube Interior Paths - potato167 1/1 3
  3. writer/tester 問題 writer tester A - Clear The Context siro53

    prd_xxx B - Miracle Dinner prd_xxx ochiaigawa C - Make Arithmetic Sequence ochiaigawa siro53 D - Tree Walking idsigma ochiaigawa E - Shinkansen idsigma siganai F - Maximum Zero Xor Prefixes ### siro53 G - GCD Must Appear ### siganai H - I like carrying up siganai ayaoni I - Hypercube Interior Paths ayaoni ### 4
  4. A - Clear The Context • 想定解法 ◦ ◦ ◦

    • どこで会話履歴を 0 にするか?を固定 (O(N)) して、O(N) でシミュレーションする 時間計算量は全体で O(N^2) 解答例 (C++23) bonus (O(N)) 解法 ◦ ◦ ◦ ◦ ◦ S_i = A_1 + A_2 + … + A_i とする i 番目で操作をすると、i+1番目以降のトークン消費量がそれぞれ S_i 減少することが分かるので、 全体的なトークン消費量は (N - i) * S_i 減る よって、前から累積和を計算しながらシミュレーションを O(1) で計算可能 時間計算量は全体で O(N) 解答例 (C++23) 5
  5. B - Miracle Dinner • 部分点解法 ◦ ◦ ◦ ◦

    ◦ ◦ ◦ x と y を足して K の倍数になるとは、x+y ≡ 0 (mod K) これは y ≡ -x (mod K) となるので、mod K で片方が x のとき他方は (K-x) とペアになる。 A,B をそれぞれ mod K で個数分布を集計したものを C,D とすると、ある時点での答えは以下 ▪ Σ_(x=0...K-1) C_x * D_(K-x) K が大きいので C,D の集計を配列でやるとTLEする 集計を map(dict) で行い、片方をループで回すと良い O(N+M) (または O((N+M)log(N+M)) 程度) で部分点に答えられる mod K の取り忘れ等に注意 6
  6. B - Miracle Dinner • 満点解法 ◦ ◦ ◦ ◦

    ◦ ◦ 部分点の答えを毎回求めるとTLE 初期状態に対する答えだけを求め、あとはクエリごとに 差分更新 をできないだろうか? 実は A,B,C,D と ans の値を管理しておくとできる 差分更新の手順 (T=1 の場合) (A,V は mod K に直しておくものとする) ▪ C[A[X]] から 1を引く ▪ ans から D[(K-A[X])%K] を引く ▪ C[V] に 1を足す ▪ ans に D[(K-V)%K] を足す ▪ A[X] を V に更新 T=2 の場合も同様 想定解は O(N+M+Q) (または O((N+M+Q)log(N+M))程度) 7
  7. C - Make Arithmetic Sequence • 想定解法① ◦ ◦ ◦

    隣接 2 要素の差分に着目します。 差分 d_i がc_i 個あるとカウントして、差分の種類数で以下のように場合分けします。 ▪ 1のとき、常にOK ▪ 2のとき、c_i = 1 となるものがあればOK ▪ 3のとき、d_1 + d_2 = 2 * d_3 かつ c_1 = c_2 = 1 のような組があれば OK ▪ 4以上のとき、常にNG 解答例 https://mofecoder.com/contests/yurufuwa_onsite_09/submissions/30278 8
  8. C - Make Arithmetic Sequence • 想定解法② ◦ ◦ ◦

    操作後の数列は下記どれかに分類されます。 ▪ A_1, A_2 が不変 ▪ A_{N-1}, A_N が不変 ▪ A_1, A_N が不変 そのため、与えられた数列 A から上の 3 種類の数列 A’ を作成し、逸脱した区間が連続1区間か つ、A’_i - A_i が全て等しければ OK です。 解答例 https://mofecoder.com/contests/yurufuwa_onsite_09/submissions/29341 9
  9. D - Tree walking - 部分点 - - すべての順列について散歩の距離が計算可能なので、頑張って実装する 満点

    - いわゆる主客転倒というやつで、i,j が隣り合うときに、頂点 i から頂点 j、または頂点 j から頂点 i の移動が生じる このような移動が起きる順列の数は、2(N-1)! - (i,j) をまとめると N-1 個の並べ方になり、i,j の並べ方が 2 通りなので これは (i,j) の組によらないため、結局 2(N-1)!×(各2頂点の最短距離の総和) が答えになる 各 2 頂点の最短距離の総和さらに辺ごとの寄与を考えると部分木のサイズを考えることで計算で きる - 適当に頂点 1 を根としたときの頂点vとその子孫のサイズを s_v とすると、s_v(N-s_v)d_(vの親 側の辺) を足し合わせればよい 10
  10. E - Shinkansen - とりあえず問題の状況の整理から 同じ側(S_i の値が等しい)から来る乗客たちは、T_i が異なるという制約から衝突し ない 左から来る乗客

    i, 右から来る乗客 j が衝突する条件を考えよう X_i < X_j のときは明らかに衝突しない 突然だが、横軸に位置、縦軸に時間を取った2次元座標を考える こうすると、各乗客の移動を2次元平面上の線分とみなすことができて、この線分 が交わるときに衝突すると言い換えられる - 乗客 i は (0,T_i) から (X_i,T_i+X_i) に移動する 乗客 j は (W,T_j) から (X_j,T_j+(W-X_j)) に移動する 12
  11. E - Shinkansen - 線分ではなく直線の交点として計算すると、衝突する可能性がある X 座標は、 (T_j+W-T_i)/2 とわかり、これが X_j

    と X_i の間にあると実際に衝突する つまり、X_j ≦ (T_j+W-T_i)/2 ≦ X_i が衝突する条件である - ここまで来れば、全探索によって部分点が得られる 13
  12. E - Shinkansen - (解法1) X_j ≦ (T_j+W-T_i)/2 ≦ X_i

    の左側と右側について、i,j ごとにまとめると次の 2 つの 不等式が得られる - - これが 2 点 i,j をマッチングできる条件 ここで新たに座標 A_i=W-T_i,B_i=2X_i+T_i,C_j=2X_j-T_j,D_j=T_j+Wとおくと、点 (A_i,B_i) と点 (C_j,D_j) をマッチングできる条件が次のように言い換えられる - - 2*X_j - T_j ≦ W - T_i かつ T_j + W ≦ 2*X_i + T_i C_j ≦ A_i かつ D_j ≦ B_i これは、2次元平面上で点 i は点 j の左下の点とマッチングできることを意味して いる 15
  13. E - Shinkansen - 解くべき問題は「赤い点 (A_i,B_i) と青い点 (C_j,D_j)」があり、C_j ≦ A_i

    かつ D_j ≦ B_iのときにマッチングできるとき、最大マッチングはいくつか?」 実はこれは貪欲法で解ける - 赤い点を A_i が小さい順に操作しながら、その時点でマッチングできる青い点のうち最もD_j が大き いものにマッチさせる https://atcoder.jp/contests/abc091/tasks/arc092_a がほぼ同じ問題で、貪欲法の証明はこの問 題の解説と同様 16
  14. E - Shinkansen (解法2) - 元々の座標に時計回りの 45 度回転をかける((x,y) -> (x+y,-x+y))と、L

    側の線分は 縦軸に、R 側の線分は横軸に平行になる(線分同士の関係性は不変) 座席に対応する方の端点を右下の図のように A,B とすると、A の左上に B があると きにマッチングできるという問題になる(あとは解法1と同様) B 時計回りに45度回転 (拡大してもよい) A 17
  15. F - Maximum Zero Xor Prefixes 0の個数の上界が floor((2^N - 1)/3)

    となることを示す。 Q_i = 0 の場合、P_{i + 1} = a, P_{i + 2} = bとすると、Q_{i + 1} = a かつ、Q_{i + 2} = a xor b だが、これは本問題の制約では、どちらも0ではない。また、Q_1 ≠ 0, Q_2 ≠ 0 なことも わかるので、 Q は (?,?,0,?,?,0,?,?,0,?,?,0,....) と3つおきに0が来るのが最大で、これは floor((2^N - 1)/3) である。 18
  16. F - Maximum Zero Xor Prefixes 実はこの上界は達成できる。Nの偶奇に応じて構築方法を示す。 Nが偶数の場合、1から2^N - 1の数を、1から2^N

    - 1に移す写像 f を以下のように定義 する。 f (x) = xをN bit表記したときに、前から2bitずつを見て、00 -> 00,01 -> 10,10 -> 11,11 -> 01 と変換された数 例えば、N = 8で2進表記した数に対して、f(11000110) = 01001011 となる。 19
  17. F - Maximum Zero Xor Prefixes fについて、以下のことが示せる。 - 1以上2^N -

    1以下の任意のxに対して、 f(f(f(x))) = x 1以上2^N - 1以下の任意のxに対して、x xor f(x) xor f(f(x)) = 0 (x,f(x),f(f(x)) という3つ組で1から2^N - 1の数のすべて列挙してそれを並べればよい N = 4のときの具体例では、(1,2,3) (4,8,12) (5,10,15) (6,11,13),(7,9,14) が3つ組になり、 Pとして、(1,2,3,4,8,12,5,10,15,6,11,13,7,9,14) を出力すれば正答となる。 20
  18. F - Maximum Zero Xor Prefixes Nが奇数の場合の構築方法を示す。 奇数の場合は、xor が0 になる

    4つ組を1つと、xorが0になる3つ組を (2^N - 5)/3 個作る と上界を達成する。 まず、(1,2,3)と(4,5,6,7)を組にして、8から2^N - 1までの数で、(2^N - 8)/3個の組を作るこ とを考える。 また、8以上2^N - 1以下の数は 8A + a (A>=1 かつ 0 <= a < 8) といった形で、あらわさ れる。 21
  19. F - Maximum Zero Xor Prefixes (8A + a,8B +

    b,8C + c) の xor が0になることは、 A xor B xor C = 0かつ、a xor b xor c = 0 であることと同値。 A,B,Cは N - 3bit (偶数bit) かつ、1以上なので、Nが偶数の場合の解法を使えばよい。 各(A,B,C)に対して、(a,b,c) として以下のような組を全て試すと、8から2^N - 1の数が全て 出てくる。 (a,b,cとして0から7までが全て出ていて、A,B,Cのいずれかに上位bitとして出て くる数は出ているので) (0,0,4),(1,3,2),(2,5,7),(3,2,1),(4,7,3),(5,0,5),(6,6,0),(7,1,6) なお、条件をみたす (a,b,c)の組は他にもある。これは手動で頑張って構築してもよいし、 全探索をしてもよい。 22
  20. F - Maximum Zero Xor Prefixes おまけ1: Nが偶数の場合のgreedy解法 3つ組を、(2^N -

    1)/3 組作れれば良い。組の選び方として、 1. 2. 3. どの組にも選ばれていない最小の数を選ぶ。 (これをxとする。) どの組にも選ばれていない数 y で、 x xor y がどの組にも選ばれてないような y の うち最小のものを選ぶ (x,y,x xor y) を組として選ぶ。 という手順を、すべての数を選ぶまで繰り返すと、実は N が偶数の場合は正当 (Nが奇 数の場合は正当ではない) 23
  21. F - Maximum Zero Xor Prefixes おまけ2: 結果的に通る乱択解法 3つ組を、floor((2^N -

    1)/3) 組作れれば良い。 1. 2. 3. 4. どの組にも選ばれていない2数をランダムに選ぶ。 (これをx,yとする。) x xor y がどの組にも選ばれない場合は、(x,y,x xor y) を組として選ぶ もし、x xor y が選ばれている場合は、すでに、(a,b,x xor y) という組があるはずなの で、この組を外して、(x,y,x xor y) を組とする。 floor((2^N - 1)/3) 組作れるまで、1~3を繰り返す (Nが奇数の場合は最後4組とする) これは N<=18 で正当となる。 https://mofecoder.com/contests/yurufuwa_onsite_09/submissions/29265 24
  22. G - GCD Must Appear 共通の考察を述べる。 - G_1,G_2,...G_N として出てくる数に着目すると、G_{i +

    1} は G_i の約数となっている。 いい順列で、G_{i + 1} < G_i のとき、P_{i + 1} = G_{i + 1} でないといけない。(G_{i + 1} はP_1からP_iの中に登場してないため、P_{i + 1}として登場しないといけない。) いい順列で、G_{i + 1} = G_i のとき、P_{i + 1}はG_iの倍数になる 逆に、この2条件を満たすような順列を数えればよい。 25
  23. G - GCD Must Appear 部分点解法1 (O(Nlog^2N)) dp[i][j] := 順列の先頭i個を決めて、gcdがjになっている場合の数

    として、dp[i][j] -> dp[i + 1][jの約数] という遷移をする。 先頭 i 個のgcdとしてあり得る数は、N/i 以下であることを考えると、 時間計算量は O(Σ_{i=1}^{N} Σ_{j=1}^{N/i} (jの約数の個数)) であり、 これは O(Nlog^2N) となる。 26
  24. G - GCD Must Appear 部分点解法2 (O(NlogN)) Gとして出てくる数から重複を除いて、出てくる順に並べた列を {d_1,d_2,...,d_k (=

    1) } とす る。 (d_{i + 1}は d_i の真の約数になる) このとき、Pは (d_1,(d_1以外のd_1の倍数),d_2,(d_2以外のd_2の倍数),...) となる。 見方を 変えると、「d_iの倍数以外で初めて出る数が、d_{i + 1}」という相対順序の定められた順 列であり、これが出る確率は Π_{i=1}^{k - 1} 1/(N - floor(N/d_i)) である。 dp[i] := 「i始まりでいい順列になる確率」として、 dp[i] = (Σ_{jはiの真の約数}dp[j])/ (N - floor(N/i)) でdpできる。 27
  25. G - GCD Must Appear 満点解法 (O(N^{3/4}) O(NlogN) の解法を高速化する。 dp[i]

    := 「iスタートのいい順列の数」として、 F(X) = Σ_{i=1}^{X} dp[i] (F(0) = 0とする。) と、Fを定めてF(N)/Nが答え dp[i]の和を floor(N/i) が同じ場所でまとめて計算することを考える 28
  26. G - GCD Must Appear Σ_{floor(N/i) = x} dp[i] =

    Σ_{floor(N/(x + 1)) < i <= floor(N/x)} dp[i] = F(floor(N/x)) - F(floor(N/(x + 1)) となる。また、O(NlogN) 解法で記載したdpの漸化式を使って、最初の式を別の方法で、 展開することを考える。 29
  27. G - GCD Must Appear Σ_{floor(N/i) = x} dp[i] =

    (Σ_{floor(N/i) = x} Σ_{j は iの真の約数} dp[j]) / (N - x) = (Σ_{k=2}^{N} Σ_{floor(N/jk) = x} dp[j]) / (N - x) jはiの真の約数なので、2以上の 整数kを用いて、i = jkとなり、そ れでiを置き換えている = (Σ_{k=2}^{N} Σ_{floor(N/k(x + 1)) < j <=floor(N/kx)} dp[j]) / (N - x) = (Σ_{k=2}^{kx<=N} F(floor(N/kx)) - F(floor(N/k(x + 1)) / (N - x) kx>Nの場合はFが0なので、見る必要なし 30
  28. G - GCD Must Appear これらをまとめると、 F(floor(N/x)) - F(floor(N/(x +

    1)) = (Σ_{k=2}^{kx<=N} F(floor(N/kx)) - F(floor(N/k(x + 1)))) / (N - x) というFに関する漸化式が出来たことになる。 この値は、floor(N/y) とあらわされる場所だけの漸化式なので、そこだけ計算すればよい。ところで、 右辺の計算は floor(N/kx) や floor(N/k(x + 1)) が同じ k でまとめると、O(√(N/x)) で計算できて、xの 大きい方から計算すると、O(N^{3/4}) の計算量になる。(※ 遷移時の逆元の計算量の記載を省略) 提出: https://mofecoder.com/contests/yurufuwa_onsite_09/submissions/29355 31
  29. G - GCD Must Appear おまけ: さらなる高速化 実は O(N^{2/3} (logN)^{1/3})

    でも解ける。 (※ 遷移時の逆元の計算量の記載を省略) Fの値はdpの累積和だったが、小さい方は普通にdpで計算して、大きい方はO(N^{3/4}) の漸化式を 使う手法て、分割位置を調整するとこの計算量になる。 詳細はこのCFのblogを見てください。 (N^{3/4}の計算量解析とかも載ってます。) https://codeforces.com/blog/entry/54150 提出(分割はテキトーにとっています。): https://mofecoder.com/contests/yurufuwa_onsite_09/submissions/29876 ※実装上はunordered_mapなどを使ってサボっていますが、配列でやったり除算の回数に気をつかうと100msは切れます。 32
  30. H - I like carrying up 想定解法 • N +

    tK と K の各桁の和がすべて 9 以下になる最小の t を求める。 • K =1012 のとき、答えは0 • それ以外の時 K の桁数は 12 桁以下となるため、繰り上がりが起こるかは X (mod 1012)を考えればよい。 • 上位 6 桁と下位 6 桁に分けて考える。B=106 とすると、下位 6 桁は、毎回 K (mod B) ずつ増えるため周期は C=B/gcd(B,K) となる。 • そのため、C 回進むと下位 6 桁は元に戻り、上位 6 桁は D=CK/B (mod B)だけ増 える。ここで、C 回進むこと 1 ループとする。 33
  31. H - I like carrying up 想定解法 • 上位 6

    桁のことを考えると、繰り上がりが起きない状態を始点に逆向きに D ずつ たどる。これにより、各状態 h (0 <= h < B) から何回ループすれば、繰り上がりが起 きない状態にたどり着くかを前計算でき、それを dist[h] とする。(何回ループしても 繰り上がりが起きる場合はINFとする。) • ここで操作回数を t = r + qC (0 <= r < C) として、各 r において繰り上がりの起こら ない最小の q を求めることを考える。 • X_r = N + rKの下位6桁で繰り上がりが起こらなければ、前計算した distを使って r + dist[ceil(X_r/B) mod B]が下位の候補となるので、これらを全ての r で求めて最 小値が答えとなる。 34
  32. I - Hypercube Interior Paths(想定解法) • Step1: 離散的な問題から連続的な問題への変換 ◦ ◦

    ◦ ◦ ◦ ◦ d 次元のときに内部の格子点を通る確率を P_d とします P_d は「ある座標が 全座標の中で最初に N に到達したときに、他のすべての座標が 1 以上になっ ている確率」だと考えられます ここで離散的な問題を連続的に捉え直します dN個の確率変数 X_{i, n}(1 <= i <= d, 1 <= n <= N) が独立に一様分布 U(0, 1) に従うと仮定します ▪ X_{i, 1}, X_{i, 2}, …, X_{i, N} を小さい順に並べ替えた値が、第 i 座標が 1, 2, …, N になる「時 刻」というモデルです 対称性より、まずは「第 1 座標が最初に N に到達する」場合を考えます。 その時刻を t = max_n X_{1, n} とします この時刻 t において条件を満たすには、ほかのすべての第 i 座標(i >= 2)について以下が成り立 つ必要があります ▪ 既に 1 以上になっている:min_n X_{i, n} < t ▪ まだ N に到達していない:max_n X_{i, n} > t 35
  33. I - Hypercube Interior Paths(想定解法) • Step1: 離散的な問題から連続的な問題への変換 ◦ ◦

    よって、時刻 t で第 1 座標が最初に N に到達し、他のすべての座標が条件を満たしている確率密 度は、Nt^{N-1}(1-t^N-(1-t)^N)^(d-1) となります ▪ X_{1, n} の中から最大値となる変数の選び方が N 通り、残りの N-1 個は t 未満になるので、 確率密度は Nt^{N-1} ▪ 他の第 i 座標は以下の2つの場合 以外なら条件を満たすので、確率は 1-t^N-(1-t)^N • まだ 1 も進んでいない:確率 (1-t)^N • 既に N 到達済み:確率 t^N どの次元が最初に N に到達するかの d 通りがあるので、P_d は以下の定積分の値として与えられ ます ▪ この積分を各 d について独立に冪乗を展開して求めようとすると、1回あたり O(Ndlog(Nd)) 、 全体で O(ND^2 log(ND)) の時間がかかり TLE してしまいます 36
  34. I - Hypercube Interior Paths(想定解法) • Step2: ベータ関数を用いた変形 ◦ ◦

    ◦ 被積分関数を多項定理で変形していき、計算量を削減することを考えます そこで登場するのが、 ベータ関数 です 以下のベータ関数の性質を利用し変形を進めていくと、次のページのようになります 37
  35. I - Hypercube Interior Paths(想定解法) • Step2: ベータ関数を用いた変形 ◦ ◦

    ◦ ◦ ◦ C_l は畳み込みの形になっているので、FFT を用いて C_0, C_1, …, C_{D-1} を計算量 O(DlogD) で 求めることができます P_d も畳み込みの形になっているので、FFT を用いてP_1, P_2, …, P_D を計算量 O(DlogD) で求め ることができます 多項式の係数は 0!, 1!, …, (ND)! とその逆数を前計算しておく必要があり、計算量 O(ND) で求める ことができます 以上より計算量 O(ND+DlogD) で計算することができました 解答例(PyPy3) 39
  36. I - Hypercube Interior Paths(おまけ) • 元ネタ 原案は 3 次元の場合であり、そこから改造されて今の形になりました

    ▪ 3 次元の場合は綺麗な式になるので、興味のある方は是非考えてみてください ◦ • 裏話 ◦ ◦ ◦ 元々は D 次元以下の全ての次元に対して答えを問う問題ではなく、D 次元の場合のみを問う問題 でした(D <= 2×10^5, ND <= 2×10^7) 積分表示を素直に計算する O(NDlog(ND)) 解法ですが、以下の理由から通すのは難しいと考えて いました ▪ 多項式の冪乗は定数倍が重い ▪ 2×10^7 >= 2^23 であり、多項式の積が重くなる(998244353 - 1 = 119×2^23) しかし、AIを酷使することで 2.5sec 程度で AC できることが判明し 、今の D 次元以下をすべて求 める問題に改題されました 40