CODE THANKS FESTIVAL 2014 A日程 解説
-
Upload
atcoder-inc -
Category
Education
-
view
648 -
download
1
description
Transcript of CODE THANKS FESTIVAL 2014 A日程 解説
CODE THANKS FESTIVAL 2014 A日程 解説
AtCoder株式会社 代表取締役
高橋 直大
2014/12/12 1
©AtCoder Inc. All rights reserved. 2
A問題 カメツル算
2014/12/12 2
A問題 問題概要
• カメがA匹、ツルがB羽います。
• 足の本数を求めなさい。
• 制約
• 1≦A, B≦1000
2014/12/12 3
A問題 アルゴリズム
• A×4+B×2を出力しよう!
– 罠とかは何もないです!
2014/12/12 4
©AtCoder Inc. All rights reserved. 5
B問題 バッジ
2014/12/12 5
B問題 概要
• バッジを N 個作りたいです。
• 3 つの機械(ちょうど 1 分経つとバッジを作る)を順繰りに動かすことができます。
• 動かす順番をうまく決めたときに、N 個作るまでにかかる時間の最小値を求めてください。
• 1 ≦ N ≦ 1,000
• 1 ≦ A ≦ 1,000
• 1 ≦ B ≦ 1,000
• 1 ≦ C ≦ 1,000
B問題 全探索による解法
• 機械の動かす順番は
A→B→C→A→… A→C→B→A→…
B→A→C→B→… B→C→A→B→…
C→A→B→C→… C→B→A→C→…
の 6 通りあります。
• すべての組み合わせを試して、一番短い時間で出来たものを答えとして出力します。
B問題 貪欲法による解法
• 実は最初の 3 回は、生産量の多い機械を優先して作るように決めても最適解が出ます。
• なぜなら、かかった時間 t について、t の値が
3 の倍数+0 ⇒ すべての機械が同じだけ動くのでどの順でも一緒
3 の倍数+1 ⇒ 最初 1 つだけ多く動くので先頭の生産量が多いと得
3 の倍数+2 ⇒ 最後以外多く動くので先頭 2 つの生産量が多いと得
となるからです。
©AtCoder Inc. All rights reserved. 9
C問題 コンテスト
2014/12/12 9
C問題 問題概要
• N問のコンテストがあり、M問の問題が解けた。
• 問題の配点と、解けた問題が与えられる。
• 得られた得点を出力しなさい。
2014/12/12 10
C問題 アルゴリズム
• 配点と解けた問題が与えられるので、素直に解けた問題に対応する点数を足し算していけば良い
• 1-indexedなので、配列にそのまま入れると1つずれていることに注意!
2014/12/12 11
©AtCoder Inc. All rights reserved. 12
D問題 定期券
2014/12/12 12
D問題 問題概要
• 1 駅ごとに 100 円の運賃がかかる路線がある
• 定期券の圏内の移動分には運賃がかからない
• 駅 a から駅 b への定期券を持っている人が
• 駅 s から駅 t へ行くときにかかる運賃は?
2014/12/12 13
D問題 問題概要
• 1 駅ごとに 100 円の運賃がかかる路線がある
• 定期券の圏内の移動分には運賃がかからない
• 駅 a から駅 b への定期券を持っている人が
• 駅 s から駅 t へ行くときにかかる運賃は?
– この質問が 105 回来る → 高速に答える必要あり
2014/12/12 14
D問題 アルゴリズム
• 基本的には (t - s) × 100 円かかる
• そこから定期券の範囲と被っている部分を引く
2014/12/12 15
D問題 アルゴリズム
• 区間の共通部分の計算をしたい
• min(b, t) - max(a, s) が共通部分の長さ
2014/12/12 16
D問題 アルゴリズム
• min(b, t) - max(a, s) が負のときは共通部分なし
• 0 との max をとれば OK
2014/12/12 17
©AtCoder Inc. All rights reserved. 18
E問題 儀式
2014/12/12 18
E問題 概要
• 縦 R 行、横 C 列の各マスに南向きの石像がある。
• 区間を指定して、90 度左に回転させる動作を N 回行う。
• 1 回だけ忘れた結果、南向きの石像が M 個になった。
• 忘れた操作として考えられるものを昇順に出力せよ。
• 1 ≦ R ≦ 50
• 1 ≦ C ≦ 50
• 1 ≦ N ≦ 5,000
E問題 すべての可能性を試す場合
• N 個の操作それぞれについて、残り N – 1 個の操作を順に実行してみた場合を考えると、計算量が O(RCN2) となってしまいます。
• ほとんど同じ操作を行っているのでうまくまとめて処理したいです。
E問題 考察
• 各手順 [S1][S2]…[SN] は可換です。
• そのため、各 [Si] について、その領域を右に 90 度回転させる(逆の操作をする)操作を [Ti] とおくと、
[S1][S2]…[S(i-1)][S(i+1)][S(i+2)]…[SN]
=( [S1][S2]…[S(i-1)][S(i+1)][S(i+2)]…[SN] ) ( [Si][Ti] )
= [S1][S2]…[SN][Ti]
が成り立ちます。
E問題 解法
• 最初に D=[S1][S2]…[SN] の結果を求めておきます。
• 各 i に対して、 [S1][S2]…[SN][Ti](=D[Ti]) の結果を求め、南向きの石像がいくつあるか数えます。
• その個数がちょうど M 個ならば手順 i は解となります。
• 計算量は O(RCN) となります。
E問題 その他の解法
• ある連続する番号[a,b] について、a 番目の手順から b 番目の手順までをすべて実行したときにそれぞれの石像が90度回転する回数を計算するには、segment-tree を用いることで実現できます。
• 各 i について、[1,i-1] と [i+1,N] の作用を segment-tree で計算することで、全体で O(RCNlogN) で計算できます。
©AtCoder Inc. All rights reserved. 24
F問題 順位表
2014/12/12 24
F問題 問題概要
• コンテスト参加者の人数Nと、「誰が誰より順位が上だった」というM個の情報が与えらる
• 高橋君(参加者1)の順位として、考えられる最も高い順位を出力しなさい
• 1≦N, M≦50
2014/12/12 25
F問題 考察
• 具体例を考えてみる
– 上に繋がっているのが順位が上
2014/12/12 26
F問題 考察
• 具体例を考えてみる
– 上に繋がっているのが順位が上
– 直接上に繋がっているところは
順位が上
2014/12/12 27
F問題 考察
• 具体例を考えてみる
– 上に繋がっているのが順位が上
– 直接上に繋がっているところは
順位が上
– そこから上に繋がるものも上
2014/12/12 28
F問題 考察
• 具体例を考えてみる
– 上に繋がっているのが順位が上
– 直接上に繋がっているところは
順位が上
– そこから上に繋がるものも上
– 上に行くだけで辿り着けない
人は、順位が上か不明
– 繋がっていないところも不明
2014/12/12 29
? ?
?
?
?
?
?
?
F問題 考察
• 具体例を考えてみる
– 上に繋がっているのが順位が上
– 直接上に繋がっているところは
順位が上
– そこから上に繋がるものも上
– 上に行くだけで辿り着けない
人は、順位が上か不明
– 繋がっていないところも不明
– 繋がっていないところは
全部自分より下な場合もある!
2014/12/12 30
? ?
?
?
?
?
?
?
F問題 アルゴリズム
• 先ほどの考察により、「上にだけ移動することにより到達可能な人」のみを、自分より上の順位だとすれば良い。
• これは、深さ優先探索や、幅優先探索などの、単純な探索で求めることが出来る。
• 計算量はO(N + M)
2014/12/12 31
©AtCoder Inc. All rights reserved. 32
G問題 通勤電車と気分
2014/12/12 32
G問題 問題概要
• N 人の人が K 個の席 (1~K) に座っていく
• それぞれの人が席を選ぶ戦略は 2 通り
– 戦略A: 空席のうち番号が最も小さいものに座る
– 戦略B: 空席で、両隣も空席であるもののうち番号が最も小さいものに座る
• i 人目の人は pi %の確率で戦略 A を、100 - pi %の確率で戦略 B をとる。
• N 人目までが席を選び終えたとき、空席の個数の期待値を求めよ。
2014/12/12 33
G問題 全探索?
• それぞれの人の気分を全部試す (2^N 通り)
• 気分が決まればその確率がわかり、席の状態はシミュレーションすれば決まる。
• TLE (部分点の 30 点はとれる)
2014/12/12 34
G問題 戦略を観察
2014/12/12 35
G問題 戦略を観察
2014/12/12 36
G問題 戦略を観察
2014/12/12 37
G問題 戦略を観察
2014/12/12 38
G問題 DP (動的計画法)
• dp[n][i][j] := 人 n までが席を選び終わったとき、
– 人のいる席のうち最も番号が大きいのは席 i で
– 席 1 ~ 席 i - 1 のうち j 個が空席
• となっている確率
として、これを計算していく
2014/12/12 39
G問題 席の状態の遷移 (戦略A)
2014/12/12 40
G問題 席の状態の遷移 (戦略B)
2014/12/12 41
G問題 計算量
• 席の状態は全部で O(NK^2) 通り
• 遷移は戦略 A, B の 2 通り
• 全体で計算量は O(NK^2)
• 100 点
2014/12/12 42
©AtCoder Inc. All rights reserved. 43
H問題 模様替え
2014/12/12 43
概要
• 縦 R 行、横 C 列の各マスに文字列が書かれている。
• 2 * 2 以上の領域で、点対称な形になっているものの総数を求めよ。
• 1 ≦ R ≦ 250
• 1 ≦ C ≦ 250
• 条件を満たす例(入力例1より)
c o d
d o c
k s
s k
部分点解法1
• 取り出す領域の左上と右下を固定し、1 つ 1 つ比較して実際にうまくいくかを試す。
• 候補が O(R2C2) 個あり、それぞれの検証にO(RC) かかるので、全体で O(R3C3) かかる。
• R および C が 20 以下なら解ける。
α β γ δ
ε ζ ζ ε
δ γ β α
記号が同じ場所をチェックする。
文字列の比較の高速化(1/3)
• 文字列の比較部分を高速化できないだろうか?
• 点対称かどうかを判定する際に 1 文字 1 文字判定するのではなく、文字列としてまとめて判定したい!
• 点対称というのは、上側を左から右に読んだものと、下側を右から左(上側の場合とは逆向き)に読んだものとが等しいということをうまく使えそう!
α β γ δ
ε ζ ζ ε
δ γ β α
どちらもαβγδになっている!
文字列の比較の高速化(2/3)
• 文字列の比較には、ローリングハッシュという手法を用いることで高速に比較することができます。
• 具体例としては、定数 X と mod する数 M を決めておいて、文字列 S のハッシュ値 H を
H′ = str の 𝑖 文字目を表す整数 ∗ X𝑖−1 |str|𝑖=1 とし
たとき、H′ を M で割った余りと定めます。
• 例えば、X= 10 , M = 999で、各文字を表す整数をアルファベットの順番としたとき、文字列 abcd のハッシュ値は H′ = 1 ∗ 100 + 2 ∗ 101 + 3 ∗ 102 + 4 ∗103(= 4321)から H=325 (325=4321-999*4) となります。
文字列の比較の高速化(3/3)
• ハッシュ値が異なる文字列同士は、確実に違う文字列と言えます。
• ハッシュ値が同じ場合は、同じ文字列である可能性があります。
• 理論上は異なる文字列同士のハッシュ値が衝突する場合があり、100% 同じ文字列であるという保証はありませんが、M をでかくとる、複数のハッシュ値を試す、などの対策をとっておけば高めの確率で衝突を回避できます。
• ある区間[a,b]のハッシュ値H([a,b])は、
H([a,末端])-H([b,末端])*X(区間[𝑎,𝑏]の要素数)で計算できます。
ローリングハッシュを用いた場合
• 先ほどの比較で各文字ごとに比較していたものが、各列ごとの比較で済むようになり、次数が 1 つ減り、5 乗オーダーとなります。
• 今回の場合は 5 乗だと時間制限に間に合わない可能性があります。
• そのため、次に 4 乗にする方針を考えます。
• 方針1: 文字列ではなく、長方形領域に関するローリングハッシュを用いる。
• 方針2: DP を用いる。
部分点解法2 - 方針 1 の場合
• H′ = str の 𝑖 文字目を表す整数 ∗ X𝑖−1 |str|𝑖=1 という式を変形し
て、
H′ = 区間の 𝑖 行目の左から 𝑗 文字目を表す整数 ∗ X𝑖−1 ∗ Y𝑖−1
𝑖,𝑗
のような変形をして全体同士の比較をすれば、全体で O(R2C2) で動作します。 • 実装に関しては2次元の累積和を求めるようにたし引きします。
H([a,b]*[c,d]) = H([a,末端]*[c,末端]) -H([b+1,末端]*[c,末端])*(累乗) -H([a,末端]*[d+1,末端])*(累乗) +H([b+1,末端]*[d+1,末端])*(累乗)
部分点解法2 - 方針 2 の場合
• 外側の比較を行い、内側はより小さケースの結果をメモしたものを使用することで、文字列のハッシュで O(R2C2) で実現できます。
• この場合、メモリ制限に注意してください。
外周部をローリングハッシュで、内側は先に計算した結果を利用
さらなる高速化
• これよりも早くする場合、答えの個数が O(R2C2) 個
あることから、複数の解をまとめて数え上げるような方針が必要となります。
• 中心を固定して考えることにします。
(以降の説明では中心が特定のマスの中央にある場合について考えていますが、他の場合も同様です。)
考察(1/3)
• ある領域で点対称だとすると、その領域の横幅を縮めても中心が同じなら同様に点対称となる。
• 高さを固定して、その中で最も左にある(横幅の大きい)ものを求めれば、それより右の部分は確かめなくても数え上げることができる。
中心
考察(2/3)
• 最も左にある(横幅の大きい)状態から、縦幅を大き
くすると、横幅は短くなる場合はあるものの、長くなる場合はない(前の段階でもっと横幅を大きく取れることになり矛盾)。
中心
考察(3/3)
• 以上 2 点をまとめると、下図のようにうねうね遷移するしゃくとり法が出てくる。
→
→ → ↑
→ ↑
→ ↑
↑
→ → ↑
↑ (中心)
しゃくとり法詳細
• 縦幅最小で横幅最大の状態からスタート。
• 点対称となるまで、上側端と下側端のみについて比較し(それ以外は既に点対称だとわかっている)、失敗したら横幅を短くする。
• 点対称となったら、そのときの幅から、中心と高さが定まった場合の点対称なデザインの個数がわかるので、これを答えに加算して縦幅を大きくしてまた横に比較する。を繰り返す。
• 横幅が 0 になったり、外部にはみ出したら終了。
• これをすべての中心について試す。
満点解法
• 先ほどのしゃくとりをすべての中心について試す。
• 中心の候補は O(RC) あり、各しゃくとりでO(R + C) かかるので、全体で O(RC(R + C)) となる。
備考
• ローリングハッシュを使用しなくても、接尾辞配列を用いることでも同じことができます。
• こちらの場合は衝突による間違いがありませんが、実装や計算量が異なり、制限時間に注意する必要があります。
©AtCoder Inc. All rights reserved. 59
おわり!
2014/12/12 59