-
Notifications
You must be signed in to change notification settings - Fork 0
276. Paint Fence #32
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
276. Paint Fence #32
Conversation
hayashi-ay
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
良いと思います。行列の解法は見てないです
| return num_ways_helper(n, k) | ||
| ``` | ||
| 思考ログ: | ||
| - cacheを配列で取った版 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nとkのtupleとかをキーにしてdictで管理するのが良いのかなと思います。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
と思いましたが、そもそもkの値は固定なのでnについてだけで良いですね。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ありがとうございます。
あ、これかなり無駄なことしてますね。。ボケてました。
|
良さそうです 強いて言えば、 |
|
ありがとうございます。 ポストを一個ずつ塗っていって、ここまではN通り、次、みたいなイメージだったのでso_farを付けたんだと思います。 |
| - https://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A3%E3%83%9C%E3%83%8A%E3%83%83%E3%83%81%E6%95%B0 | ||
| - 行列表現の結果をもとに漸化式を作る | ||
| - q = n//2として、q-1, q, q+1番目のフィボナッチ数を用いてn番目のフィボナッチ数を表すことができる(lognに落とせる) | ||
| - 漸化式に2nと2n-1を代入して確かめれば、そうなってるなあとなるが、、結構テクい式変形に感じた |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
この式を見ると若干テクい感じに見えますが、計算量のオーダー的には以下のような事と同じです。
(再帰を上から展開していくか、桁の下の方からボトムアップに計算していくかみたいな違いです。)
import numpy as np
def fib(n):
result = np.array([[1 , 0], [0, 1]])
fib_array = np.array([[1 , 1], [1, 0]])
val = 1
while val <= n:
val *= 2 # ビットシフト
if n % val: # log(val, 2)桁目のbitが立っているとき
n -= n % val
result = result.dot(fib_array)
fib_array = fib_array.dot(fib_array)
return result[0][1]※この実装はnumpyの数値行列なのでオーバーフローがあり、実用上の価値はあまりないかもしれません。あくまでも概念的な説明でした。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
実装例もありがとうございます。
行列のn乗で計算できることから、律儀に行列をn回掛けるのでなく、(n=2^kとしてざっくり)k=logn個の道中のk乗行列を計算しておけばいいよね、ということだと理解しました。
ちょっと頂いたコードの流れがよく追えてないので少し考えてみます。。(n -= n % valあたり)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
これ変なコードですみません、ビットシフトの知識を前提にしない方がわかりやすいかもと思って、余計意味不明になってしまいました。。。
-=しているのは、チェックした部分までに立っているビットをすべてクリアする意図でした。
要は、fib_array ** nを、2進展開の要領でn = 2^{k_1} + 2^{k_2} + ... + 2^{k_m} みたいに分解して、積を取っています。
例えばn=10のとき、n=2^3+2^1ですが、(fib_array ** 8) * (fib_array ** 2)とするとき、このカッコの中身たちは自乗で効率的に計算ができるということでした。
このn乗を効率的に計算する方法は、フィボナッチ数列に限らず任意の行列で使えます。
(ただ、巨大数の積や大きな行列の演算は高コストなので、任意の行列などでやると、一般にはlog(n)よりも大きなオーダーになりがちだと思います)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-=しているのは、チェックした部分までに立っているビットをすべてクリアする意図でした。
ありがとうございます。理解しました。
大きな行列の演算は高コスト
スパースな行列の場合はうまく工夫できたりと色々奥が深いですよね。
色々と詳細にありがとうございました。
またコメントよろしくお願いします!
| - https://discord.com/channels/1084280443945353267/1251052599294296114/1272143005851058229 | ||
| > あー、あと、この問題、行列の n 乗なので、そういう方法でも計算できるはずです。 | ||
| - 漸化式から行列表記にして、n乗を計算する | ||
| - 普通に累乗するとコストが大きそうなので、対角化して累乗計算する |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
大きさ次第ですが、2次の正方行列の n 乗は、偶奇で場合分けして半分にしていけば、対角化しなくてもいいですね。
対角化、固有値計算、逆行列計算、次数が上がるとそれなりに重いです。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
よくよく考えるとそうですね。。
ケーリーハミルトンの定理で頑張っていた頃を思い出しました。
leetcode: https://leetcode.com/problems/paint-fence/description/
lintcode: https://www.lintcode.com/problem/514/