Loading [MathJax]/jax/output/CommonHTML/jax.js

日本最強プログラマー学生選手権~Advance~ -予選- (AtCoder Beginner Contest 412)D,E,F問題メモ

D - Make 2-Regular Graph

問題文

  • N 頂点 M 辺の単純無向グラフ G があります。頂点には 1,2,,N の番号が付けられており、i 番目の辺は頂点 Ai と頂点 Bi を結ぶ無向辺です。
  • あなたは、以下の 2 つの操作を好きな順序で好きな回数繰り返すことができます。
    • G に無向辺を 1 つ追加する
    • G から無向辺を 1 つ削除する
  • G をすべての頂点の次数が 2 である単純無向グラフにするために行う操作回数として考えられる最小値を求めてください。

制約

  • 3N8
  • 0MN(N1)2
  • 入力で与えられるグラフ G は単純無向グラフ
  • 入力される値はすべて整数

解法

意外と時間かかった。
次数が全て2ということを上手く使うには少し知識が要る。

次数が全て2のグラフは、置換グラフ(を無向辺にしたもの)に限られる。

  • 置換グラフ:
    • 順列 P に対し、iPi に辺を張った有向グラフ
    • 全ての連結成分はサイクルとなる

N が小さく 8!=40320 程度なので、 全ての順列について、それから生成される置換グラフになるように辺を追加したり削除したりすると 操作回数はいくつになるか、を実際に試せる。

  • 全ての既存の辺を削除してから、置換グラフの辺を追加すると N+M 回の操作が必要
  • 置換グラフの辺が初めから存在していたら、そこから削除+追加の2回を節約できる

と考えると、1回の順列の試行は O(N)、全体 O(N!) となる。

ただし、P[P[i]]=i となるような i が存在する順列は、単純グラフにならないので除外する必要がある。

Python3

E - LCM Sequence

問題文

  • 正整数 n について An1,2,,n の最小公倍数として定義します。
  • 正整数 L,R が与えられます。数列 (AL,AL+1,,AR) の中には何種類の整数が含まれますか?

制約

  • 1LR1014
  • RL107
  • L,R は整数

解法

区間篩、難しいわけじゃないし制約も特徴的なのに、出されるといっつも忘れてるね。
(ミラーラビンでごにょごにょしようとしていた)

2数 a,b が素因数分解して a=px1qy1rz1b=px2qy2rz2 となるとき、 LCM(a,b)=pmax(x1,x2)qmax(y1,y2)rmax(z1,z2) である。
素因数ごとに、肩に乗っている指数の最大値が使われる。

これを踏まえると、nAn を更新するのは、 「n の素因数分解の結果に、n 未満のどの整数よりも指数の大きな素数がある」場合に限られる。

言い換えると、「ある単一の素数 p と1以上の整数 x を使って、px と表せる数」に限られる。

x=1x2 で場合分けする。

x=1 の時は、つまり素数である。
区間篩で素数を O((R+D)loglogR) で列挙できる。(D=RL とする)

x=2 の時は、pR である。
R 以下の素数を列挙し、xR を超えるまで1ずつ増やし、LpxR のものを記録しておけばよい。
PRR 以下の素数の個数とし、O(R+PRlogR) で求められる。

あとは、L+1R の中にある“An を更新する値”の個数+1が答えとなる。
L は、An を更新する値かどうかに関わらず必ず1種類に数えられる点に注意)

Python3

F - Socks 4

問題文

  • 高橋君のタンスの中には N 色の靴下があり、色 i の靴下は Ai 枚あります。
  • 高橋君ははじめこれらの靴下とは別に色 C の靴下を 1 枚タンスの外に持っており、操作を終える条件を満たすまで以下の操作を繰り返します。
    • タンスから靴下を 1 枚一様ランダムに選んで取り出す。
    • その後、タンスの外に持っている 2 枚の靴下が同じ色ならば操作を終える。
    • そうでないならば、片方の靴下を選んでタンスに戻す。
      • ただし、高橋君は常に今後の靴下を取り出す回数の期待値が最小となるようにタンスに戻す靴下を選ぶ。
  • 操作を終えるまでに靴下を取り出す回数の期待値を mod 998244353 で求めてください。

制約

  • 1N3×105
  • 1CN
  • 1Ai3000
  • 入力される値はすべて整数

解法

S=iAi(タンスの中の靴下の数)とする。

また、これ以降、AC+=1 とし、A はタンスの外を含め全体の靴下の枚数を示すとする。

ある操作で取り出した靴下の色が違うなら、 期待値の上では枚数が多い方を残すのが明らかによい。
同率の場合はどちらでも変わらないが、適当に全ての大小関係をつけておく。

Ai を降順に並べ替える。(C も、並べ替えた後の対応する index に変化するとする)

その上で、以下に示す E1,E2,...,EC を順に求めていける。

  • Ti:=i の靴下を持った状態
  • Ei:=i の靴下を持った状態からの残り回数期待値
  • j<i なる j に対しては、確率 AjSTj に遷移する。
  • i を確率 Ai1S で引くと、終了する。
  • i<j なる j に対しては、引き続き Ti のままとなる。
  • Ei=j<iAjSEj+Ai1S×0+SEi+1
i   1  2  3  4  5  6  ...
E   *  *  *<-*
    ^  ^-----|
     `-------'
     
   ~~~~~~~~~                ... Σ(jへの遷移確率 × Ej)
               ~~~~~~~      ... i=4以降の靴下を引く確率 × Ei

Ei が右辺にも左辺にも登場するので、適宜式変形して解く。

  • 現在の j<i なる j に対する AjS×Ej の総和
  • 現在の j<i なる j に対する Aj の累積金額

あたりを更新しながら i を進めていくと、1回当たり O(1) または O(logmod) の計算量で解ける。

Python3

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