日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

矩阵的乘法和快速幂的一些理解(适用初学者)

發布時間:2025/3/15 编程问答 16 豆豆
生活随笔 收集整理的這篇文章主要介紹了 矩阵的乘法和快速幂的一些理解(适用初学者) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

矩陣是線性代數的知識。。。后悔沒好好學了。。。

?

第一部分:矩陣的基礎知識

1.結合性?(AB)C=A(BC).

2.對加法的分配性?(A+B)C=AC+BC,C(A+B)=CA+CB?.

3.對數乘的結合性?k(AB)=(kA)B?=A(kB).

4.關于轉置?(AB)'=B'A'.

一個矩陣就是一個二維數組,為了方便聲明多個矩陣,我們一般會將矩陣封裝一個類或定義一個矩陣的結構體,我采用的是后者。

?

第二部分:矩陣相乘

若A為n×k矩陣,B為k×m矩陣,則它們的乘積AB(有時記做A·B)將是一個n×m矩陣。

其乘積矩陣AB的第i行第j列的元素為:

?

舉例:A、B均為3*3的矩陣:C=A*B,下面的代碼會涉及到兩種運算順序,第一種就是直接一步到位求,第二種就是每次求一列,比如第一次,C00+=a00*b00,C01+=a00*b01……第二次C00+=a00*b10,C01+=a01*b11……以此類推。。。

C00 = a00*b00 + a01*b10 + a02*b20

?

C01 =?a00*b01 + a01*b11 + a02*b21?

?

?

C02 =?a00*b02 + a01*b12 + a02*b22

?

?

C10 =?a10*b00 + a11*b10 + a12*b20

?

?

C11 =?a10*b00 + a11*b11 + a12*b21

?

?

C12 =?a10*b02 + a11*b12 + a12*b22

?

?

C20 =?a20*b00 + a21*b10 + a22*b20

?

?

C21 =?a20*b01 + a21*b11 + a22*b21

?

?

C22 =?a20*b02 + a21*b12 + a22*b22

?

?

C00 = a00*b00 + a01*b10 + a02*b20

?

?

C01 =?a00*b01 + a01*b11 + a02*b21?
C02 =?a00*b02 + a01*b12 + a02*b22

?

?

具體該怎么實現兩個矩陣相乘呢?

一般會用O(n^3)的方法。。。配合剪枝【添條件,設門檻。。。】,如下:其實主要就是函數 MATRIX mat_multiply (MATRIX a , MATRIX b , int n);

const int MOD=10000; struct mat { int a[2][2];//這里數據范圍就用小的示范 }; mat mat_mul(mat x,mat y)//實現兩個矩陣相乘,返回的還是一個矩陣。 { mat res;//用來表示得到的新的矩陣; memset(res.a,0,sizeof(res.a)); for(int i=0;i<2;i++) for(int j=0;j<2;j++) for(int k=0;k<2;k++) { res.a[i][j]+=x.a[i][k]*y.a[k][j]; res.a[i][j]%=MOD;//這一步看題目具體需要了 } return res; }

?

學了現代的話這個是很好理解的(個人認為)。

?

?

?

第三部分:矩陣快速冪 ? //其實和普通快速冪類似,只不過這里需要得到的是一個矩陣

神馬是冪?【很多時候會被高大上的名字嚇到。。。導致學習效率降低。。。其實沒辣么可怕,很簡單!!!】

冪又稱乘方。表示一個數字乘若干次的形式,如n個a相乘的冪為a^n ,或稱a^n為a的n次冪。a稱為冪的底數,n稱為冪的指數。——引自.度娘百科

這類題,指數都是很大很大很大很大很大很大很大的。。。霸王硬上弓的話,很容易超時的 T_T 。。。所以得快速冪→_→

學過之后發現,其實矩陣快速冪 的核心思想跟 以前學過的快速冪取模非常非常相似,只是矩陣乘法需要另外寫個函數,就是上面那個代碼。。。

?

快速冪的思路就是:

設A為矩陣,求A的N次方,N很大,1000000左右吧。。。

先看小一點的,A的9次方

A^9

= A*A*A*A*A*A*A*A*A ?【一個一個乘,要乘9次】

= A*(A*A)*(A*A)*(A*A)*(A*A)【保持格式的上下統一,所以加上這句】

?= A*(A^2)^4?【A平方后,再四次方,還要乘上剩下的一個A,要乘6次】

= A*((A^2)^2)^2【A平方后,再平方,再平方,還要乘上剩下的一個A,要乘4次】

?

也算是一種二分思想的應用吧,1000000次冪,暴力要乘1000000次,快速冪就只要(log2底1000000的對數) 次,大約20次。。。這。。。我沒錯吧。。。

?

?單位矩陣: n*n的矩陣 mat ( i , i )=1; 任何一個矩陣乘以單位矩陣就是它本身 n*單位矩陣=n, 可以把單位矩陣等價為整數1。(單位矩陣用在矩陣快速冪中)

?

例如下圖就是一個7*7的單位矩陣:

?

?

?

下面來實現一個矩陣快速冪:

?

?

int pow(int n)//還是小范圍數據來說吧,要不然返回值的類型自己定義 { mat c,res; memset(res.a,0,sizeof(res.a)); c.a[0][0]=1;//給矩陣賦初值 c.a[0][1]=1; c.a[1][0]=1; c.a[1][1]=0; for(int i=0;i<n;i++) res.a[i][i]=1;//單位矩陣; while(n) { if(n&1) res=mat_mul(res,c);//這里看就要用到上面的矩陣相乘了; c=mat_mul(c,c); n=n>>1; } return res.a[0][1]; }//時間復雜度log(n)

?? ? 但是矩陣如何與斐波那契聯系在一起呢???

找了很多博客,看了第二位大神的博客才理解。

?

對于矩陣乘法與遞推式之間的關系:

?

如:在斐波那契數列之中

f[i] = 1*f[i-1]+1*f[i-2] ?f[i-1] = 1*f[i-1] + 0*f[i-2];

所以

就這兩幅圖完美詮釋了斐波那契數列如何用矩陣來實現。

?

? 下面一POJ3070/NYOJ148為例

? 給出了矩陣相乘的定義,要你求出斐波那契的第n項對1e4取余。

1.針對題目給出的矩陣:

所以這里我是直接求解n次冪,答案就是a[0][1];

#include<bits/stdc++.h> using namespace std; typedef long long ll; const int MOD=10000; struct mat { ll a[2][2]; }; mat mat_mul(mat x,mat y) { mat res; memset(res.a,0,sizeof(res.a)); for(int i=0;i<2;i++) for(int j=0;j<2;j++) for(int k=0;k<2;k++) res.a[i][j]=(res.a[i][j]+x.a[i][k]*y.a[k][j])%MOD; return res; } void mat_pow(int n) {mat c,res; c.a[0][0]=c.a[0][1]=c.a[1][0]=1; c.a[1][1]=0; memset(res.a,0,sizeof(res.a)); for(int i=0;i<2;i++) res.a[i][i]=1; while(n) { if(n&1) res=mat_mul(res,c); c=mat_mul(c,c); n=n>>1; } printf("%I64d\n",res.a[0][1]); } int main() {int n; while(~scanf("%d",&n)&&n!=-1) { mat_pow(n); } return 0; }

2.利用遞推式,此時的Fibonacci[0]=0,和題目相對應,所以這里就是n-1次冪

#include<set> #include<map> #include<list> #include<queue> #include<deque> #include<cmath> #include<stack> #include<cstdio> #include<string> #include<bitset> #include<vector> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> using namespace std;#define e exp(1) #define pi acos(-1) #define mod 1000000007 #define inf 0x3f3f3f3f #define ll long long #define ull unsigned long long #define mem(a,b) memset(a,b,sizeof(a)) int gcd(int a,int b){return b?gcd(b,a%b):a;}const int MOD=10000; struct mat { ll a[2][2]; }; mat mat_mul(mat x,mat y) { mat res; memset(res.a,0,sizeof(res.a)); for(int i=0;i<2;i++) for(int j=0;j<2;j++) for(int k=0;k<2;k++) res.a[i][j]=(res.a[i][j]+x.a[i][k]*y.a[k][j])%MOD; return res; } void mat_pow(int n) {mat c,res; c.a[0][0]=c.a[0][1]=c.a[1][0]=1; c.a[1][1]=0; memset(res.a,0,sizeof(res.a)); for(int i=0;i<2;i++) res.a[i][i]=1; while(n) { if(n&1) res=mat_mul(res,c); c=mat_mul(c,c); n=n>>1; } printf("%I64d\n",res.a[0][0]); } int main() {int n; while(~scanf("%d",&n)&&n!=-1) {if(n==0)printf("0\n");else mat_pow(n-1);}return 0; }

?

?

總結

以上是生活随笔為你收集整理的矩阵的乘法和快速幂的一些理解(适用初学者)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。