14
yukicoder No. 194 フィボナッチ数列の理解(1) 出題/解説 kmjp 1

yukicoder : No.194 フィボナッチ数列の理解(1)

  • Upload
    kmjp

  • View
    216

  • Download
    4

Embed Size (px)

Citation preview

Page 1: yukicoder : No.194 フィボナッチ数列の理解(1)

yukicoder No. 194 フィボナッチ数列の理解(1)

出題/解説 kmjp

1

Page 2: yukicoder : No.194 フィボナッチ数列の理解(1)

問題

• スーパーフィボナッチ数列第k項の 値F(𝑘)は:

– 𝑘 ≤ 𝑁の時:𝐹 𝑘 = 𝐴𝑘

– 𝑘 > 𝑁の時:𝐹 𝑘 = 𝐹(𝑘 − 𝑖)𝑁𝑖=1

• 整数Kに対し𝐹 𝐾 と𝑆 𝐾 = 𝐹 𝑖𝐾𝑖=1 を

答えよ

2

Page 3: yukicoder : No.194 フィボナッチ数列の理解(1)

解法:前半ケース • 愚直に式通り計算すると計算量Ο 𝑁𝐾 でTLE

• 𝐹 𝑘 を𝑆 𝑖 を用いて変形する

• 𝐹 𝑘 = 𝐹(𝑘 − 𝑖)𝑁𝑖=1 = 𝑆 𝑘 − 1 − 𝑆 𝑘 − 𝑁 − 1

• 𝑆 𝑘 = 𝑆 𝑘 − 1 + 𝐹(𝑘)

• 𝑆 1 ~𝑆 𝑘 − 1 から𝐹 𝑘 と𝑆 𝑘 を順次求める

• 計算量はΟ 𝐾

3

Page 4: yukicoder : No.194 フィボナッチ数列の理解(1)

解法:後半ケース(1) • Kが大きいのでΟ 𝐾 では間に合わない

– 以下蟻本の「行列累乗」と同内容

• 漸化式を行列で表現する。以下N=4の例

• この行列は漸化式を1つ進める行列と見なせる

– コンパニオン行列と呼ぶそうです

1 1 1 11 0 0 00 1 0 00 0 1 0

𝐹𝑘𝐹𝑘−1𝐹𝑘−2𝐹𝑘−3

=

𝐹𝑘 + 𝐹𝑘−1 + 𝐹𝑘−2 + 𝐹𝑘−3𝐹𝑘𝐹𝑘−1𝐹𝑘−2

=

𝐹𝑘+1𝐹𝑘𝐹𝑘−1𝐹𝑘−2

𝐹𝑘+1と等しい(そうなるよう行列を作る)

4

Page 5: yukicoder : No.194 フィボナッチ数列の理解(1)

解法:後半ケース(2) • 前述の正方行列の(𝐾 − 𝑁)乗を求めれば、𝐹 1 ~𝐹 𝑁 から 𝐹 𝐾 が求められる

• (𝐾 − 𝑁)乗を行列累乗で求めるとΟ 𝑁3 log𝐾

1 1 1 11 0 0 00 1 0 00 0 1 0

𝐾−4 𝐹4𝐹3𝐹2𝐹1

=

𝐹𝐾𝐹𝐾−1𝐹𝐾−2𝐹𝐾−3

5

Page 6: yukicoder : No.194 フィボナッチ数列の理解(1)

解法:後半ケース(3) • 𝑆 𝑘 についても同様の行列を考えられる 𝑆 𝑘 = 𝑆 𝑘 − 1 + 𝐹 𝑘 = 2 × 𝑆 𝑘 − 1 − 𝑆 𝑘 − 𝑁 − 1

• 𝑆 𝐾 と𝑆 𝐾 − 1 を求めれば 𝐹 𝐾 = 𝑆 𝐾 − 𝑆(𝐾 − 1)で𝐹 𝐾 もわかるので 実はこちらの行列だけ計算すれば十分

2 0 0 0 −11 0 0 0 00 1 0 0 00 0 1 0 00 0 0 1 0

𝐾−4 𝑆4𝑆3𝑆2𝑆1𝑆0

=

𝑆𝐾𝑆𝐾−1𝑆𝐾−2𝑆𝐾−3𝑆𝐾−4

6

Page 7: yukicoder : No.194 フィボナッチ数列の理解(1)

解法:後半ケース(4) • 以下の行列でも𝐹 𝑘 と𝑆 𝑘 をまとめて 計算できる

1 1 1 1 10 1 1 1 10 1 0 0 00 0 1 0 00 0 0 1 0

𝑆𝑘𝐹𝑘𝐹𝑘−1𝐹𝑘−2𝐹𝑘−3

=

𝑆𝑘+1𝐹𝑘+1𝐹𝑘𝐹𝑘−1𝐹𝑘−2

7

Page 8: yukicoder : No.194 フィボナッチ数列の理解(1)

別解

• Ο 𝑁2 log 𝐾 解法:通称きたまさ法

–蟻本第二版に「Ο 𝑁2 log𝐾 で解けるよ」と 書いてあるが解き方は書かれていない

– http://d.hatena.ne.jp/wata_orz/20090922/1253615708

– https://dl.dropboxusercontent.com/u/109915284/companion20140318.pdf

– http://yosupo.hatenablog.com/entry/2015/03/27/025132

– に解説があるが、詳細まで書かれておらず玄人向け

• もう少し実装寄りの解説をしてみます

–長いので所感の後で

8

Page 9: yukicoder : No.194 フィボナッチ数列の理解(1)

元ネタ・所感

• プロコンを知らない人にアルゴリズムの威力を知ってもらうために考えていた問題

– Ο 𝑁𝐾 → Ο 𝐾 → Ο 𝑁3 log𝐾 で驚かす

– 元々yukicoder以外で使う予定でした

• 元々解説は行列累乗解で終わる予定でした

– その後きたまさ法の詳細を知り、慌てて調査

– 結果的に作問側も勉強になりました

• おかげでTDPC 問Tも解けた

• 頑張って解説書いたけど、先にyosupoさんのブログ(3/27)でさらっと解説されててつらい

9

Page 10: yukicoder : No.194 フィボナッチ数列の理解(1)

通称きたまさ法(1)

• 𝐹𝑥は𝐹1から𝐹𝑁の加算で生成するので

𝐹𝑥 = 𝐴𝑥,1𝐹1 + 𝐴𝑥,2𝐹2 + … = 𝐴𝑥,𝑖𝐹𝑖𝑁𝑖=1

と表現可能

• 𝐴𝐾,1~𝐴𝐾,𝑁がわかれば𝐹1~𝐹𝑁は既知なので 𝐹𝐾も計算できる

–実は𝐴𝐾,1~𝐴𝐾,𝑁 は5ページの行列の(K-N)乗における1行目の値に相当する

• 行列全体の累乗をさぼって必要なところだけ 計算する手法とも言える

10

Page 11: yukicoder : No.194 フィボナッチ数列の理解(1)

通称きたまさ法(2)

• 2つの基本的なアイデアを組み合わせる

• アイデア1

– 𝐴𝑥,𝑖と𝐴𝑦,𝑖から𝐴𝑥+𝑦,𝑖を計算

–これができれば数値の累乗テクの応用で

𝐴1,𝑖 , 𝐴2,𝑖 , 𝐴4,𝑖 , 𝐴8,𝑖…から𝐴𝐾,𝑖を計算可能

• アイデア2

– 𝐹𝑥 = 𝐴𝑥,𝑖𝐹𝑖𝑖 なら𝐹𝑥+𝑗 = 𝐴𝑥,𝑖𝐹𝑖+𝒋𝑖

– 𝐴𝑥,𝑖は𝐹𝑥に𝐹𝑖の何倍が加算されるかを示す

• すなわち(𝑥 − 𝑖)個前の項の何倍が加算されるかを 示す値と考えられる。

11

Page 12: yukicoder : No.194 フィボナッチ数列の理解(1)

通称きたまさ法(3)

• 𝐹𝑥+𝑦 = 𝐴𝑥+𝑦,𝑖𝐹𝑖𝑖 = 𝐴𝑥,𝑖𝐹𝑦+𝑖𝑖

• 𝐹𝑦+𝑖 = 𝐴𝑦+𝑖,𝑗𝐹𝑗𝑗 = 𝐴𝑦,𝑗𝐹𝑖+𝑗𝑗

• 上記2式を合わせると

• 𝐹𝑥+𝑦 = 𝐴𝑥,𝑖𝐴𝑦,𝑗𝐹𝑖+𝑗𝑗𝑖

–二重ループで𝐴𝑥,𝑖𝐴𝑦,𝑗は𝐹𝑖+𝑗の何倍が𝐹𝑥+𝑦に加算されるか示す値なので 𝐴𝑥+𝑦,𝑖+𝑗 += 𝐴𝑥,𝑖𝐴𝑦,𝑗と処理できる

– 𝑖 + 𝑗 > 𝑁のケースはどうする?

赤字はアイデア2 による変形箇所

12

Page 13: yukicoder : No.194 フィボナッチ数列の理解(1)

通称きたまさ法(4) • 𝑖 + 𝑗は高々2Nなので先に𝑘 ≤ 2𝑁の範囲で𝐴𝑘,𝑖を求めておく – 二重ループ処理後、𝑙 > 𝑁に対し各𝑚 ≤ 𝑁に 𝐴𝑥+𝑦,𝑚 += 𝐴𝑥+𝑦,𝑙𝐴𝑙,𝑚でその分の影響を加算する

• 以下N=4の場合

k 𝐴𝑘,1 𝐴𝑘,2 𝐴𝑘,3 𝐴𝑘,4

1 1 0 0 0

2 0 1 0 0

3 0 0 1 0

4 0 0 0 1

5 1 1 1 1

6 1 2 2 2

7 2 3 4 4

8 4 6 7 8

事前に 計算

13

Page 14: yukicoder : No.194 フィボナッチ数列の理解(1)

通称きたまさ法(5)

• まとめ

– 𝑘 ≤ 2𝑁の範囲で𝐴𝑘,𝑖を求めておく

– 𝐴𝑥,𝑖から𝐴2𝑥,𝑖を計算

• 𝐴𝑥+𝑦,𝑖+𝑗 += 𝐴𝑥,𝑖𝐴𝑦,𝑗を適宜処理

• 𝑙 > 𝑁の場合 𝐴𝑥+𝑦,𝑚 += 𝐴𝑥+𝑦,𝑙𝐴𝑙,𝑚

–累乗テクの応用で𝐴2𝑛,𝑖から𝐴𝐾,𝑖を計算

–これを理解すると、Typical DP Contestの 最終問題が解けます

–実装例 http://yukicoder.me/submissions/13712

14