矩阵快速幂

基础概念

利用矩阵快速幂加快递推式的计算
对于形如\(f(n)=af(n-1)+bf(n-2)+cf(n-3)+df(n-4)+...\)的递推式,以\(f(n)=af(n-1)+bf(n-2)+cf(n-3)+df(n-4)\)为例,我们可以利用矩阵快速幂的方式加快递推式的计算。
首先得出一个矩阵定义式:

\[A(n)=[f(n),f(n-1),f(n-2),f(n-3)],B为4*4方阵 \]

B的大小由递推项的个数决定,例子f(n)由4项组成,所以B为4*4方阵
矩阵递推式:

\[A(n)=A(n-1)*B \]

A矩阵初项:

\[A(4)=[1,1,1,1] \]

B矩阵,首列为原递推式的对应系数,除第一列,最后一行以外右上部分为单位阵

\[B=\begin{bmatrix} a&1&0&0\\ b&0&1&0\\ c&0&0&1\\ d&0&0&0\\ \end{bmatrix} \]

最终:

\[A(n)=A(4)*B^{n-1} \]

则,最终的f(n)就是B的第一列和(前4项不一定成立,需特判)

板子

2023.8 最新整理板子 2

int n;
const int mod = 998244353;
struct Matrix{
	static const int N = 15;
	ll a[N][N];
	Matrix(ll e = 0){
		for(int i = 1; i <= n; ++ i)
			for(int j = 1; j <= n; ++ j)
				a[i][j] = e * (i == j);
	}
	Matrix mul(Matrix A, Matrix B){
		Matrix ans(0);
		for(int i = 1; i <= n; ++ i){
			for(int j = 1; j <= n; ++ j){
				for(int k = 1; k <= n; ++ k){
					ans.a[i][j] = (ans.a[i][j] + A.a[i][k] * B.a[k][j]) % mod;
				}
			}
		}
		return ans;
	}
	Matrix ksm(Matrix A, ll b){
		Matrix ans(1);
		while(b){
			if(b & 1) ans = mul(ans, A);
			A = mul(A, A);
			b >>= 1;
		}
		return ans;
	}
};

板子1
全部功能外置,记得给矩阵赋初值

const int N=2;
struct matrix{
	int m[N][N];
};

matrix operator *(const matrix a,const matrix b){
	matrix c;
	memset(c.m,0,sizeof(c.m));
	for(int i=0;i<N;++i){
		for(int j=0;j<N;++j){
			for(int k=0;k<N;++k){
				c.m[i][j]=(c.m[i][j]+a.m[i][k]*b.m[k][j])%mod;
			}
		}
	}
	return c;
}
matrix qpow_matrix(matrix a,int x){
	matrix c;
	memset(c.m,0,sizeof(c.m));
	for(int i=0;i<N;++i) c.m[i][i]=1;
	while(x){
		if(x&1) c=c*a;
		a=a*a;
		x>>=1;
	}
	return c;
}

板子2,利用struct聚合
记得给n赋值

struct Matrix{
	static const int N=15;
	ll a[N][N];
	Matrix(ll e=0){
		for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) a[i][j]=e*(i==j);
	}
	Matrix mul(Matrix A,Matrix B){
		Matrix ans(0);
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				for(int k=1;k<=n;k++){
					ans.a[i][j]=(ans.a[i][j]+A.a[i][k]*B.a[k][j])%mod;
				}
			}
		}
		return ans;
	}
	Matrix ksm(Matrix A,ll b){
		Matrix ans(1);
		while(b){
			if(b&1) ans=mul(ans,A);
			A=mul(A,A);b>>=1;
		}
		return ans;
	}
}tmp;

相关习题

  1. Fibonacci
    矩阵快速幂加速递推模板题,前提就是找到那个基础的矩阵
    此题,\(n≥2\)时,\(A=\begin{bmatrix} 1&1\\ 1&0\\ \end{bmatrix}\)\(A^n={\begin{bmatrix} F_{n+1}&F_n\\ F_n&F_{n-1}\\ \end{bmatrix}}^n\)
    所以\(F_n\)即为左下角的第一个数
    \(F_0与F_1\)已经给定了
    下见代码:
//>>>Qiansui
#include<map>
#include<set>
#include<stack>
#include<cmath>
#include<queue>
#include<deque>
#include<cstdio>
#include<string>
#include<vector>
#include<utility>
#include<iomanip>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define ull unsigned long long
#define mem(x,y) memset(x,y,sizeof(x))
//#define int long long

inline ll read()
{
	ll x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
	return x*f;
}

using namespace std;
const int maxm=2e5+5,inf=0x3f3f3f3f,mod=10000,N=2;

struct matrix{
	int m[N][N];
};

matrix operator *(const matrix a,const matrix b){
	matrix c;
	memset(c.m,0,sizeof(c.m));
	for(int i=0;i<N;++i){
		for(int j=0;j<N;++j){
			for(int k=0;k<N;++k){
				c.m[i][j]=(c.m[i][j]+a.m[i][k]*b.m[k][j])%mod;
			}
		}
	}
	return c;
}
matrix qpow_matrix(matrix a,int x){
	matrix c;
	memset(c.m,0,sizeof(c.m));
	for(int i=0;i<N;++i) c.m[i][i]=1;
	while(x){
		if(x&1) c=c*a;
		a=a*a;
		x>>=1;
	}
	return c;
}

void solve(){
	int c;
	matrix a,b;
	a.m[0][0]=1;
	a.m[0][1]=1;
	a.m[1][0]=1;
	a.m[1][1]=0;
	while(cin>>c){
		if(c==-1) break;
		b=qpow_matrix(a,c);
		cout<<b.m[1][0]<<"\n";
	}
	return ;
}

signed main(){
	//ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	int _=1;
//	cin>>_;
	while(_--){
		solve();
	}
	return 0;
}
  1. Geometric Progression
    乍一眼是乘法逆元,但是并不是每个数都存在乘法逆元。
    这题得先观察一个规律——\(\begin{pmatrix} a_X\\ 1\\ \end{pmatrix}=\begin{pmatrix} A&1\\ 0&1\\ \end{pmatrix}^X \begin{pmatrix} 0\\ 1\\ \end{pmatrix}\),之后利用矩阵快速幂求解
    详见提交代码
posted on 2023-05-08 20:40  Qiansui  阅读(18)  评论(0编辑  收藏  举报