C++ 矩陣快速冪
阿新 • • 發佈:2018-12-10
在學這個之前學了好一陣子矩陣,仍然不太懂。。後來發現解斐波那契數列好像只需要方形矩陣就行了,就學了一下方形矩陣的乘法。
思路:首先,假定我們會快速冪。
那麼如何寫矩陣快速冪呢?
我們需要明確一件事,我們寫的快速冪實際上是:十進位制數字快速冪
十進位制數字的單位是1。而矩陣的單位是單位矩陣
那麼,是不是我們只要把十進位制數字的單位"1"換成"單位矩陣"就可以寫矩陣快速冪了?
答案是是的。不過需要注意一個細節:由於十進位制和矩陣的乘法規則不一樣,因此矩陣的乘法需要額外寫一個方法。
上程式碼吧
#include<cstdio> #include<iostream> #define ll long long #define mod 1000000007 using namespace std; struct Mat{ ll m[101][101]; }; Mat initMat(int n); Mat Mul(Mat a,Mat b,int n); Mat poww(Mat a,ll b); Mat a,e;//a:輸入 e:單位矩陣 int n;//矩陣長度 (每行n個數 ) int main(){ Mat a; int k;//k是Mat的指數 cin>>n>>k;//input 矩陣長度以及指數 for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ cin>>a.m[i][j]; } } //初始化e for(int i=0;i<n;i++){ e.m[i][i]=1; } Mat c=poww(a,k); for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ cout<<c.m[i][j]%mod<<" "; } cout<<endl; } return 0; } Mat poww(Mat a,ll b){ Mat ans=e,base=a; while(b!=0){ if(b&1){//如果是奇數 ans=Mul(ans,a,n);//DEBUG重點 原: Mul(ans,ans,n) } base=Mul(base,base,n); b=b/2; } return ans; } Mat Mul(Mat a,Mat b,int n){//相乘 //方形矩陣 n:矩陣長或寬 Mat c=initMat(n); for(int i=0;i<n;i++){//乘到的行數 for(int x=0;x<n;x++){//x座標 for(int y=0;y<n;y++){//y座標 c.m[i][x]=c.m[i][x]%mod+a.m[i][y]*b.m[y][x]%mod; //c.m[i][x]=c.m[i][x]%mod+a.m[x][i]*b.m[x][y]%mod; } } } return c; } Mat initMat(int n){//初始化矩陣 n:方形矩陣長或寬 Mat c; for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ c.m[i][j]=0; } } return c; }
zxc大佬的指點
1.n,k應為long long型別
2.快速冪的過程中應為 ans=Mul(ans,a,n);
AC程式碼如下:
#include<cstdio> #include<iostream> #define ll long long #define mod 1000000007 using namespace std; struct Mat{ ll m[101][101]; }; Mat initMat(int n); Mat Mul(Mat a,Mat b,int n); Mat poww(Mat a,ll b); Mat a,e;//a:輸入 e:單位矩陣 ll n;//矩陣長度 (每行n個數 ) int main(){ Mat a; ll k;//k是Mat的指數 cin>>n>>k;//input 矩陣長度以及指數 for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ cin>>a.m[i][j]; } } //初始化e for(int i=0;i<n;i++){ e.m[i][i]=1; } Mat c=poww(a,k); for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ cout<<c.m[i][j]%mod<<" "; } cout<<endl; } return 0; } Mat poww(Mat a,ll b){ Mat ans=e,base=a; while(b!=0){ if(b&1){//如果是奇數 ans=Mul(ans,base,n);//DEBUG重點 原: Mul(ans,ans,n) } base=Mul(base,base,n); b=b/2; } return ans; } Mat Mul(Mat a,Mat b,int n){//相乘 //方形矩陣 n:矩陣長或寬 Mat c=initMat(n); for(int i=0;i<n;i++){//乘到的行數 for(int x=0;x<n;x++){//x座標 for(int y=0;y<n;y++){//y座標 c.m[i][x]=c.m[i][x]%mod+a.m[i][y]*b.m[y][x]%mod; //c.m[i][x]=c.m[i][x]%mod+a.m[x][i]*b.m[x][y]%mod; } } } return c; } Mat initMat(int n){//初始化矩陣 n:方形矩陣長或寬 Mat c; for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ c.m[i][j]=0; } } return c; }
總結:
1.應該仔細看好題目的範圍要求
2.快速冪的 ans=Mul(ans,base,n); 應當理解透徹