學習筆記:矩陣
今天講了矩陣……就總結一下好了
http://blog.csdn.net/tomorrowtodie/article/details/52311373
http://www.matrix67.com/blog/archives/276 矩陣經典例題
很多內容來自學姐課件
矩陣
啥是矩陣?這個很好懂吧?
(不懂我也沒辦法)
大體就長這樣
矩陣乘法
蛤?兩個矩陣怎麽做乘法?並不是所有矩陣都能做乘法的。
只有n行p列的矩陣和p行m列的矩陣才可以相乘。
相乘完就是一個n*m的矩陣嘍。
就這樣子。左邊的每一行分別去和右邊的每一列相乘,然後取和
比如取了左邊的第二行和右邊的第一列相乘
那麽他們的和就應該放在結果的第二行第一列上。
代碼如下:
1 for (int i=1;i<=n;++i) 2 for (int j=1;j<=m;++j) 3 for (int k=1;k<=p;++k) 4 c[i][j]+=a[i][k]*b[k][j];
代碼是不是看起來很水?理解了就很好懂了……
WARNING!
矩陣乘法不滿足交換律!即A*B!=B*A
但矩陣乘法滿足結合律!即A*B*C=A*(B*C)
矩陣乘法的應用
恩……說了這麽多矩陣乘法究竟該怎麽用呢?
FIRST 矩陣乘法優化DP
這可能是矩陣乘法用的最多的地方了吧……
舉個栗子
求Fibonacci數列第n項的值
n<=1018
數據這麽大要是一步步安穩遞推我們怕不是要TLE到飛起
那就走個捷徑好了
快速冪!
……
哎等等不是應該用矩陣乘法嗎
如圖
哎這樣是不是就能做了?
先給上式中第二個矩陣命名為P,給矩陣[F[2],F[1]]命名為A
那麽[F[3],F[2]]就可以用矩陣A*P計算得出。同理
若求F[10]就可以A*P8,而P8我們就可以用快速冪求了
復雜度為log級別。模板如下:
1 struct Mar 2 { 3 int a[N][N]; 4 } unit, A,ans; 5 //PS這裏的unit為單位矩陣,即左上角到右下角對角線為1的矩陣,它有一個性質,即為任何矩陣乘上單位矩陣都為本身 6 Mar Mul(Mar a, Mar b)//矩陣乘法 7 { 8 Mar ans; 9 memset(ans.a,0,sizeof(ans.a)); 10 for (int k=1; k<=n; ++k) 11 for (int i=1; i<=n; ++i) 12 for (int j=1; j<=n; ++j) 13 ans.a[i][j]=(ans.a[i][j]+a.a[i][k]*b.a[k][j])%Mod; 14 return ans; 15 } 16 Mar Qpow(Mar a,int p)//矩陣快速冪 17 { 18 Mar ans=unit;//相當於快速冪中的初始化為1 19 while (p!=0) 20 { 21 if (p&1) 22 ans=Mul(ans,a); 23 a=Mul(a,a); 24 p>>=1; 25 } 26 return ans; 27 }
練習
已知遞推式F(n)=2*F(n-1)+3*F(n-2),求F(n)
已知遞推式F(n)=F(n-1)+3*F(n-2)+4*F(n-4),求F(n)
已知遞推式F(n)=sigma(i=1..10)a[i]*F(n-i),讀入a[i]數組,求F(n)
BZOJ1898 沼澤鱷魚
(核心:12為一個周期)
SECOND 圖的鄰接矩陣+矩陣乘法
????
這是個啥玩意兒?
構造無向圖的鄰接矩陣G
G*G以後得到一個什麽東西? (GG)
可發現
如果(i,j)=1並且(j,k)=1
那麽G*G的(i,k)+=1
經過了兩條邊!
G^k 即為經過了k條邊,
可以擴展到有向圖
若想要可以在一個點停留
如果不允許走回頭路呢?
對於一個無向圖,我們可以將邊變為點,若從能點a經過邊i到b,再從點b經過邊j到c,那麽就化邊為點,設i,j兩邊可以相互抵達,用鄰接矩陣存即可,類似上面的不能在一個點停留。
例:BZOJ1875 HH去散步
矩乘DP的特點?
一般看到那種某個限制的範圍非常小的就可以考慮一下矩乘
但是也有可能是狀壓
如果一個限制非常小,一個限制非常大,那基本上就是矩乘了
long long 太慢了!
少取模!
學習筆記:矩陣