先道個歉啦
這次的教學文拖了5天才po@@
好啦那開始了
這次要講的是矩陣快速冪!
關於快速冪的部分
可以先去看以前的教學文哦
至於矩陣的乘法以及相關特性
麻煩還不知道的各位可以去翻數學課本
(應該是高二的課本)
或是維基百科也可以
https://zh.wikipedia.org/wiki/%E7%9F%A9%E9%99%A3%E4%B9%98%E6%B3%95
在這裡就不再重複說明了
接下來就是正文啦
應該會有人好奇吧
「啊考試那種考矩陣A^100的題目
用矩陣快速冪也沒用
那為什麼我們需要矩陣快速冪?」
是誰說沒有的
我之前數學段考想不出來就真的給他快速冪
花了好幾分鐘但是有算對啊!
沒 沒事 那時候的我怪怪的
首先 我們先來看一個大家很熟悉的東西──費氏數列
1 1 2 3 5 8 13 21 ……
矩陣快速冪和費氏數列有什麼關聯呢?
最一般求費氏數列第n項的做法
就是直接
a[0]=1; a[1]=1;
for (int i=2; i<=n; i++) a[i]=a[i-1]+a[i-2];
這麼做的時間複雜度是O(n)
遇到求第10^18項mod 10^9+7這種題目就GG了
(我猜會有人好奇哪個題目這麼變態
請參考2016年NPSC的pF.無限兔子問題
一個我想出難的部份結果漏掉簡單的部分最後TLE的題目= =
那題和費氏數列有關
解法也是矩陣快速冪
不過有點麻煩就是了)
那麼 該怎麼加速呢?
這時候 矩陣乘法就派上用場了!
註:
這裡先定義
F[i]表示費氏數列第i項
矩陣A表示下面這個2*2的矩陣
1 1
1 0
矩陣X[i]表示下面這個2*1的矩陣
F[i+1]
F[i]
(如果不習慣我用字母表示矩陣的話
可以自己在紙上把矩陣再寫一遍哦
我覺得看過原本寫成矩陣的樣子可以幫助自己的記憶
但是在這裡寫成矩陣排版會跑掉
所以麻煩大家自己動動手了)
如果把矩陣A乘上X[n] 會變成什麼呢?
新的2*1矩陣
下面那個數字是1*F[i+1]=F[i+1]
而上面那個數字呢?
發現了嗎?
1*F[i+1]+1*F[i]=F[i+2]
也就是說
A乘上X[n]會得到X[n+1]!
「啊用矩陣去算
還不是要乘n-1次
還比用加的更慢齁」
嘿!接下來就可以用快速冪加速啦
如果要求第n項
就是A*(……A*(A*(A*X[0]))……)=X[n]
(前面共n個A)
根據矩陣乘法的性質
上面的可以改寫成
(A*A*……*A)*X[0]
(一樣是n個A)
=A^n*X[0]
而A^n就可以用之前說過的快速冪去算啦
只是把數字的乘法改成矩陣乘法而已
Code:
http://codepad.org/o2QPKVoN
(當然啦
一般項求解也是個方法
但是電腦處理根號5會有浮點數誤差
而且每出現一種新的數列就要重新推一次一般項
不是很實用
所以就不列在這裡了)
好啦這次的教學文就到這邊了
有問題都歡迎提出來討論
然後如果我文章中有可以改進的地方
也麻煩跟我說一下哦!
下一篇:組合數
你可能有興趣的文章...
全部留言
個人覺得,應該要先會dp在教如何把它轉成矩陣吧(? 就是如果轉移式都是常數,轉成矩陣,快速冪一下,結束(? 像是這題w http://toj.tfcis.org/oj/pro/416/ 這題可以用組合數寫 只是我排組是垃圾,所以直接拿DP幹下去w
就是因為不行,所以才要轉成矩陣啊w 而且可以滾動,所以應該可以吧(?
通常judge可以扛到10^9/秒(? 所以理論上應該不會tle (?
可是judge扛的10^9/秒是乘過常數的吧 如果O(n)還要把常數算進去的話 感覺n=10^9的時候有點危險@@ (其實我不確定 不同judge的速度不一樣@@)