55
AtCoder Regular Contest 039 解説 AtCoder株式会社 代表取締役 高橋 直大 1

AtCoder Regular Contest 039 解説

Embed Size (px)

Citation preview

AtCoder(Regular(Contest(039解説

AtCoder株式会社(代表取締役(

高橋(直大

1

競技プログラミングを始める前に

• 競技プログラミングをやったことがない人へ(– まずはこっちのスライドを見よう!(

– http://www.slideshare.net/chokudai/abc004

2

©AtCoder(Inc.(All(rights(reserved. 3

A問題(A(C(B(Problem

解説スライド担当: 森田 晃平

A問題 問題概要

• 3桁の整数A,(Bが与えられる(

• 1桁だけ書き換えることができる(

• A(C(Bを最大化せよ(

• ただし100の位を0に書き換えてはいけない

4

A問題 アルゴリズム

• Aはできる限り大きくしたい(

• Aのどこかを書き換えるなら9にするべき(

• Bはできる限り小さくしたい(

• Bのどこかを書き換えるなら?(

- 1,(10の位を書き換えるなら0にするべき(

- 100の位を書き換えるなら1にするべき

5

A問題 アルゴリズム

• つまり書き換え方は6パターン(

- Aの1の位を9に(

- Aの10の位を9に(

- Aの100の位を9に(

- Bの1の位を0に(

- Bの10の位を0に(

- Bの100の位を1に

6

A問題 アルゴリズム

7

全部試す!

A問題 アルゴリズム

• 文字列(10進数)⇔数字の相互変換が出来ると楽です

8

int a = 123;string a_str = to_string(a);a_str[0] = '9';int new_a = stoi(a_str);printf("%d %d\n", a, new_a); //123 923

C++11による一例を載せておきます

©AtCoder Inc. All rights reserved.

B問題 高橋幼稚園 解説スライド:三上和馬

1. 問題概要2. 考察3. アルゴリズム

1

B問題 問題概要

• N人の児童にK個のキャンディを配る• 全体の幸福度=(各児童に与えられたキャンディの個数の積)

• 全体の幸福度が最大となるような配り方の総数を求めよ• ただし答えは大きいので,10^9+7で余りを取ること• 1≦N≦100, 1≦K≦500

2

B問題 考察

• 最大となるような配り方はどんなものか考える• 結論を言うと,N≦Kのとき,できるだけ均等に分けると最大• たとえばN=4,K=10のとき順番を無視すれば,

3個 3個 2個 2個

• というふうに配ると最大になる.

• したがって,– (K/Nを切り捨てた値)個は少なくとも全員に配れるので必ず配る

– 残りのK%N個を各児童に高々1つ分配する• という分配方法の総数を求める問題になる

3

B問題 考察

• N=4,K=10のケースを図で表してみる– (K/Nを切り捨てた値)=2– K%N=2

• なので,固定キャンディを□,動かせるキャンディを■で表すと– □□■– □□■– □□– □□

• ■の分配方法の総数=N個の中からK%N個を選ぶ組み合わせの総数

• =𝑁 𝐶𝐾%𝑁(図のケースだと4𝐶2 = 6が答え

4

B問題 考察

• しかし,N>Kのときどう配っても全体の幸福度は0になってしまうので,均等に分配する必要はなく,どんな配り方をしてもよい

• したがって答えは,K個のものをN個の箱に分配する組み合わせの個数に等しい

• この組み合わせの総数は𝑁𝐻𝐾 =𝑁+𝐾−1 𝐶𝐾で表される

• この等式の証明はネットで検索するとたくさん分かりやすい解説が見つかるので,導出方法も含めてきちんと理解しておくと良い

5

B問題 アルゴリズム

• 考察をまとめると以下のようなプログラムを書けば良い– N ≦ Kのとき𝑁𝐶𝐾%𝑁 を10^9+7で割った余りを出力

– 𝑁 > 𝐾のとき𝑁+𝐾−1𝐶𝐾を10^9+7で割った余りを出力

• N≦Kのケースしか考慮していない場合は80点しか取れないような部分点を設定した

• nCrの求め方は次のスライドの24ページ目を参考にしてください: http://www.slideshare.net/chokudai/abc021

• 今回は,パスカルの三角形を直接生成する方法で間に合います

6

©AtCoder Inc. All rights reserved.

C問題 幼稚園児高橋君 解説スライド:三上和馬

1. 問題概要2. 考察3. アルゴリズム4. 参考

7

C問題 問題概要

• 無限に広がる二次元格子があり,最初原点にいる• 上下左右のいずれかに未訪問の格子にたどり着くまで直進するという動作を繰り返す

• 各時点でどの方向を選んだかというK個の情報𝑆1, 𝑆2, 𝑆3, … , 𝑆𝐾が与えられるので,シミュレーションして最終的に辿り着いた地点を出力せよ

• 1≦K≦200000

8

C問題 考察

• 愚直に1マスずつ移動するシミュレーション• 一度の直進動作には最悪K回の移動が発生(左右に動き続けるケースを想定すると良い)

• これだととても間に合わない• そこで,各格子について上下左右の最近傍の未訪問格子の座標を記録しておき,逐次更新することを考える

• 更新方法だが,ある格子を訪問したとき,その4近傍の格子のみについて最近傍の情報を書き換えれば十分

• その情報に基づいてシミュレーションすれば即座に次の未訪問格子に辿り着ける

9

C問題 考察

• イメージは以下の通り• このような情報を全ての格子に持たせる

10

C問題 考察

• 格子を訪問済みにするときは,訪問済みにした格子の近傍情報を利用して,以下のように4近傍の格子の情報を張り替えればよい

11

C問題 考察

• 具体的には,訪問済みにする格子をxとすると

– xの右格子の左格子=xの左格子– xの左格子の右格子=xの右格子– xの上格子の下格子=xの下格子– xの下格子の上格子=xの上格子

というふうに張り替え

(左格子,右格子,…という表記は全て未訪問のものを指す)

12

C問題 考察

• 実際に格子は無限大に広がっているので,予め全格子について初期化しておくことはできない

• 情報を更新する必要が出てきたときに初めて近傍の情報を生成する方針を取る(遅延評価)

• 実際に訪問する格子はK個しかなく,訪問済み操作時も4近傍しか見ないので,情報が更新される格子はO(K)個

• 格子の近傍情報はハッシュや平衡二分探索木で管理する

• これで一度の直進動作はO(1)もしくはO(log K)で行えるようになった

13

C問題 アルゴリズム

• 近傍情報更新の遅延評価の実装方法としては,– 既に更新しようとしている格子の近傍情報が生成されてるなら新しく生成せず,それを更新する

– 生成されていないならば近傍情報を生成する• という場合分けを行うと良い• あとは近傍情報を使ってシミュレーションする

• 方向に対してインデックスを時計周りに定義するなどして,実装を軽くする工夫をしましょう!

• ハッシュマップまたは平衡二分探索木を使えば,全体の計算量は O(K) もしくは O(K log K) となる

14

C問題 参考

• このような4近傍の情報を持つデータ構造はDancingLinksと呼ばれています

• 興味がある人は調べてみてください

15

©AtCoder(Inc.(All(rights(reserved.

D問題 旅行会社高橋君

9

解説スライド担当: 森田 晃平

D問題 問題概要

• N頂点M辺の無向グラフが与えられる(

• Q個クエリが飛んでくるので処理する(

- 頂点A,(B,(Cが与えられる(

- A(C>(B(C>(C(と経由するトレイルがあるか判定(

• 制約(

- 1(<=(N(<=(100,000(- 1(<=(M(<=(200,000(- 1(<=(Q(<=(100,000

10

D問題 アルゴリズム

この問題を解くには”二重辺連結成分分解”というアルゴリズムを使用する(

11

D問題 アルゴリズム

二重辺連結成分分解とは?(

無向グラフを二重辺連結成分に分解するアルゴリズム(

二重辺連結成分とは?(

橋を含まない連結な無向グラフの事を二重辺連結成分と呼ぶ(

橋とは?(

辺(u,(v)について、その辺を取り除くと(u,(v)が連結ではなくなってしまう時その辺の事を橋と呼ぶ

12

D問題 アルゴリズム

13

橋と二重辺連結成分の例

D問題 アルゴリズム

Gが二重辺連結成分の時、Gの任意の2頂点s,(tについて(

s,(tを結ぶ、辺を共有しない2本のパス(辺素パス)が存在する(

これはGの任意の2頂点s,(tについて、s(C>(t(へとフローが2以上流せるとも考えられる(

ただし辺は全て容量1の無向辺として考える14

s

t

D問題 アルゴリズム 

Gは連結なので明らかにフローが1は流せる(

Gに橋がなければフローが2以上流せる事を示したい

15

D問題 アルゴリズム最大フロー最小カット定理を使う(

仮に最大フローが1だとすると、S,(T間に辺が1本だけ架かっているsCtカットが存在する事になる(

その1本の辺を取り除くと、(

SとTが非連結になってしまうため(

明らかに橋(

よって最大フローが1なら橋が存在する(

C>(Gに橋がなければ必ずフローが2以上流せる(

C>(Gが二重辺連結成分なら必ずフローが2以上流せる16

D問題 アルゴリズム

s,(tを結ぶ、辺を共有しない2本のパス(辺素パス)が必ず存在する事がわかった(

更に、任意の3頂点(s,(t1,(t2(について辺を共有しない(s(C(t1(パスと(s(C(t2パスが存在する事も言える

17

s

t1

t2

D問題 アルゴリズム

これは、新しい頂点xを用意して(xCt1,(xCt2という辺を貼ると、s(C(x(間に2本の辺素パスがある事からわかる

18

s

t1

t2 s

t1

t2

x

s

t1

t2

xs

t1

t2

D問題 アルゴリズム

よって、A,(B,(C(が同じ二重辺連結成分にある場合、クエリの答えは(OK(

じゃあ違う場合はどうする?

19

D問題 アルゴリズム

まず二重辺連結成分分解をして、二重辺連結成分を全部検出する(

二重辺連結成分分解は、グラフの橋を全部検出して取り除けば残ったものが全て二重連結成分(

ここで、元のグラフで二重辺連結成分を縮約して1つの頂点にしてしまうと、橋だけが辺として残り、グラフは木になる

20

D問題 アルゴリズム

21

D問題 アルゴリズム

22

α

β

γ

D問題 アルゴリズム

こうして生まれた木においてA,(B,(Cを含む頂点をそれぞれX,(

Y,(Zとすると、パス(X(C(Z(上にYが存在するかどうかがクエリの答えになる

23

XY

Z

XY

Z

A

B

C

D問題 アルゴリズム

こうして生まれた木においてA,(B,(Cを含む頂点をそれぞれX,(

Y,(Zとすると、パス(X(C(Z(上にYが存在するかどうかがクエリの答えになる

23

XY

Z

XY

Z

A

B

C

D問題 アルゴリズム

こうして生まれた木においてA,(B,(Cを含む頂点をそれぞれX,(

Y,(Zとすると、パス(X(C(Z(上にYが存在するかどうかがクエリの答えになる

23

XY

Z

この辺を2回使ってしまう

XY

Z

A

B

C

D問題 アルゴリズム

こうして生まれた木においてA,(B,(Cを含む頂点をそれぞれX,(

Y,(Zとすると、パス(X(C(Z(上にYが存在するかどうかがクエリの答えになる

23

XY

Z

この辺を2回使ってしまう

XY

Z

A

B

C

D問題 アルゴリズム

こうして生まれた木においてA,(B,(Cを含む頂点をそれぞれX,(

Y,(Zとすると、パス(X(C(Z(上にYが存在するかどうかがクエリの答えになる

23

XY

Z

この辺を2回使ってしまう

XY

Z

A

B

C よさそう

D問題 アルゴリズム

パス(X(C(Z(上にYが存在するかどうかは(

dist(X,(Z)(==(dist(X,(Y)(+(dist(Y,(Z)(で判定できる(

ただしdist(a,(b)は木でのパス(a(C(b(の長さ(

distは適当な頂点を根にしておけば、(

dist(a,(b)(=(depth(a)(+(depth(b)(C(2*depth(lca(a,(b))(で計算できる

24

LCA参考: ABC 014 D - 閉路http://abc014.contest.atcoder.jp/tasks/abc014_4

D問題 橋の列挙法

以上より二重辺連結成分分解ができればこの問題が解ける事がわかった(

そして橋の列挙ができれば二重辺連結成分分解が出来る(

じゃあどうやって橋を列挙するのか?(

lowlinkというものを使用するアルゴリズムが有名ですが、(

今回はimos法でやる方法を紹介します

25

D問題 橋の列挙法

まずはdfs木を構築し、辺を木に使われる辺と後退辺に分類します

26

D問題 橋の列挙法

後退辺ごとに、対応するパス上の辺を塗る

27

D問題 橋の列挙法

後退辺ごとに、対応するパス上の辺を塗る

27

D問題 橋の列挙法

後退辺ごとに、対応するパス上の辺を塗る

27

D問題 橋の列挙法

後退辺ごとに、対応するパス上の辺を塗る

27

D問題 橋の列挙法

後退辺ごとに、対応するパス上の辺を塗る

27

D問題 橋の列挙法

後退辺ごとに、対応するパス上の辺を塗る

27

D問題 橋の列挙法

後退辺ごとに、対応するパス上の辺を塗る

27

D問題 橋の列挙法

後退辺ごとに、対応するパス上の辺を塗る

27

これで塗られなかった辺が橋

D問題 橋の列挙法

塗るのは愚直にやればO(NM)ぐらいだが,(imos法でO(N+M)にできる

28

+1 +1

+1

-1

-1

-1

D問題

29

お疲れ様でした!