P3390 【模板】矩陣快速冪


題目鏈接

點這里

關於矩陣快速冪

矩陣定義

\(n×m\)個數\(a[i][j]\)排成的\(n\)\(m\)列的數表稱為\(n\)\(m\)列的矩陣,簡稱\(n×m\)矩陣。

矩陣加法

只有行列均相同的矩陣才有加法

運算也比較簡單,把對應位置的數相加得到一個新的矩陣,即為答案

\[\begin{bmatrix} 1 & 1 & 2 \\ 1 & 0 & 1 \end{bmatrix} + \begin{bmatrix} 2 & 3 & 3 \\ 3 & 3 & 2 \end{bmatrix} = \begin{bmatrix} 3 & 4 & 5 \\ 4 & 3 & 3 \end{bmatrix} \]

加法運算律:

\[A + B = B + A \]

\[(A + B) + C = A + (B + C) \]

#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
    int a[101][101], x, i, j;
    int n, m;
    cin >> n >> m;
    for(i=0;i<n;i++)
        for(j=0;j<m;j++)
            cin >> a[i][j];
    for(i=0;i<n;i++)
        for(j=0;j<m;j++){
            cin >> x;
            a[i][j] += x;
        }
    for(i=0;i<n;i++){
        for(j=0;j<m;j++){
            cout << a[i][j] << " ";
        }
        cout << endl;
    }
}

重載運算符的以后會在總結篇里給出...咕咕咕咕

矩陣減法

和上面一樣,把+換成-

矩陣乘法

前提條件:

一個矩陣的行數等於另一個矩陣的列數

也就是若A是\(i×j\)的矩陣,那么B必須是\(j×i\)的矩陣(對稱的)

公式:

\[C_{ij} = \sum_{i = 1}^n A_{ik} * B_{kj} \]

注意此處求解時的循環順序應為:

	for(int i=0;i<n;++i)
	{
		for(int j=0;j<n;++j)
		{
			t.m[i][j]=0;
			for(int k=0;k<n;++k)
			{
				t.m[i][j]=(t.m[i][j]+a.m[i][k]*b.m[k][j])%mod;
			}
		}
	}

想知道為什么?

因為一些緩存問題,請看luogu日報

例子:

\[\begin{bmatrix} 1 & 2\\ 2 & 3 \end{bmatrix} \times \begin{bmatrix} 2 & 4 & 5 \\ 3 & 4 & 3 \end{bmatrix} = \begin{bmatrix} 8 & 12 & 11 \\ 13 & 20 & 19 \end{bmatrix} \]

運算規律

無交換律

乘法滿足結合律,左分配律,右分配律,即

\[(A \times B) \times C = A \times (B \times C) \]

\[(A + B) \times C = A \times C + B \times C) \]

\[C(A + B) = C \times A + C \times B \]

矩陣快速冪

就是把普通的快速冪的*換成了矩陣乘法

代碼:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<string>
#include<cstring>
#define ll long long int
#define MAXN 105
#define mod 1000000007
using namespace std;
const int maxn=999999999;
const int minn=-999999999;
inline int read() {
	char c = getchar(); int x = 0, f = 1;
	while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
	while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
	return x * f;
}
ll n,k;
struct matrix
{
	ll m[105][105];
}a;
/*乘法*/
matrix cheng(matrix a,matrix b)
{
	matrix t;
	for(int i=0;i<n;++i)
	{
		for(int j=0;j<n;++j)
		{
			t.m[i][j]=0;
			for(int k=0;k<n;++k)
			{
				t.m[i][j]=(t.m[i][j]+a.m[i][k]*b.m[k][j])%mod;
			}
		}
	}
	return t;
}
/*快速冪*/
matrix quick_pow(matrix a,ll k)
{
	matrix ret=a,b=a;
	k--;
	while(k)
	{
		if(k&1) ret=cheng(b,ret);
		b=cheng(b,b);
		k>>=1;
	}
	return ret;
}
/*讀人*/
int main()
{
	cin>>n>>k;
	for(int i=0;i<n;++i)
	{
		for(int j=0;j<n;++j)
		{
			cin>>a.m[i][j];
		}
	}
	a=quick_pow(a,k);
	for(int i=0;i<n;++i)
	{
		for(int j=0;j<n;++j)
		{
			cout<<a.m[i][j]<<" ";
		}
		cout<<'\n';
	}
	return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM