• 矩阵乘法优化递推


    矩阵加减法

    对于矩阵\(A\pm B=C\),直接把每一个位置的两个元素相加或相减。
    要求:A 和 B 和 C 行列相同

    矩阵乘法

    如果 A 是个 \(n\times r\) 的矩阵、 B 是个\(r\times m\)的矩阵,则\(A\times B=C\)是个\(n\times m\)的矩阵(图片来自网络,侵删)

    \(C_{i,j}=\sum_{k=1}^r A_{i,k}\bullet B_{k,j}\)

    1. 不满足交换律\(AB\ne BA\)
    2. 满足结合律\((AB)C=A(BC)\)
    3. 满足分配率\(A(B+C)=AB+AC\)

    如何加速

    例:斐波那契

    斐波那契

    决策点只有两个,考虑矩阵乘法

    构建答案、累乘矩阵

    设答案 \(F(n)=\begin{vmatrix} f(n)&f(n-1) \end{vmatrix}\)

    需要构建 \(base\) 使得 \(F(n)*base=F(n+1)\)

    根据矩阵乘法的运算法则,一列一列的构造

    首先 \(F(n+1)=\begin{vmatrix} f(n+1) & f(n) \end{vmatrix}\)

    \(1*f(n)+1*f(n-1)=f(n+1)\)

    \(base\) 第一列是 \(\begin{vmatrix} 1 \\ 1 \end{vmatrix}\)

    \(1*f(n)+0*f(n-1)=f(n)\)

    \(base\) 第二列是 \(\begin{vmatrix} 1 \\ 0 \end{vmatrix}\)

    所以\(base=\begin{vmatrix} 1 & 1 \\ 1 & 0 \end{vmatrix}\)

    计算结果

    \(F(n)=F(2)*base^{n-2}=\begin{vmatrix} f(n)&f(n-1) \end{vmatrix}\)

    为什么是 \(F(2)\) :因为 \(F(1)\)\(f(0)\) 无意义

    代码实现中,可将 \(F(n)\) 看成 \(2\times 2\) 得矩阵,多余地方补零

    \(F(n)=\begin{vmatrix} f(n) & f(n-1) \\ 0 & 0 \end{vmatrix}\)

    快速幂初值就是 \(F(2)\) ,然后算。不能算完再乘 \(F(2)\) ,因为矩阵乘法不满足交换律

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const LL mod=1000000007;
    struct mat {
    	LL a[10][10];
    	mat() { memset(a,0,sizeof(a)); }
    	inline mat operator *(mat x) {
    		mat res;
    		for(int i=1;i<3;i++)
    			for(int j=1;j<3;j++)
    				for(int k=1;k<3;k++)
    					(res.a[i][j]+=a[i][k]*x.a[k][j])%=mod;
    		return res;
    	} 
    }tmp,res,F;
    LL n;
    inline void Pow(LL p) {
    	for(;p;p>>=1,tmp=tmp*tmp)
    	if(p&1)res=res*tmp;
    }
    int main() {
    	scanf("%lld",&n);
    	if(n<3)return puts("1"),0;
    	res.a[1][1]=1,res.a[1][2]=1;
    	res.a[2][1]=0,res.a[2][2]=0;
    	
    	tmp.a[1][1]=1,tmp.a[1][2]=1;
    	tmp.a[2][1]=1,tmp.a[2][2]=0;
    	
    	Pow(n-2);
    	
    	printf("%lld",res.a[1][1]);
    }
    

    例二

    矩阵加速(数列)

    \(F(n)=\begin{vmatrix} a(n) & a(n-1) & a(n-2) \end{vmatrix}\)

    \(base=\begin{vmatrix} 1 & 1 & 0 \\ 0 & 0 & 1 \\ 1 & 0 & 0 \end{vmatrix}\)

    然后 \(F(n)=F(3)*base^{n-3}\)

    直接求解即可

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const LL mod=1000000007;
    const int N=3;
    struct mat {
    	LL a[10][10];
    	mat() { memset(a,0,sizeof(a)); }
    	inline mat operator *(mat x) {
    		mat res;
    		for(int i=1;i<=N;i++)
    			for(int j=1;j<=N;j++)
    				for(int k=1;k<=N;k++)
    					(res.a[i][j]+=a[i][k]*x.a[k][j])%=mod;
    		return res;
    	} 
    }tmp,res;
    LL n;
    int T;
    inline void Pow(LL p) {
    	for(;p;p>>=1,tmp=tmp*tmp)
    	if(p&1)res=res*tmp;
    }
    int main() {
    	scanf("%d",&T);
    	while(T--) {
    		scanf("%lld",&n);
    		if(n<4) { puts("1"); continue; }
    		res.a[1][1]=1,res.a[1][2]=1,res.a[1][3]=1;
    		res.a[2][1]=0,res.a[2][2]=0,res.a[2][3]=0;
    		res.a[3][1]=0,res.a[3][2]=0,res.a[3][3]=0;
    		
    		tmp.a[1][1]=1,tmp.a[1][2]=1,tmp.a[1][3]=0;
    		tmp.a[2][1]=0,tmp.a[2][2]=0,tmp.a[2][3]=1;
    		tmp.a[3][1]=1,tmp.a[3][2]=0,tmp.a[3][3]=0;
    		
    		Pow(n-3);
    		
    		printf("%lld\n",res.a[1][1]);		
    	}
    }
    

    矩阵加维

    带常数项 k

    \(f(n)=f(n-1)+f(n-2)+k\),求 \(f(n)\)

    对常数项多加一维,常数得递推式是 \(k_n=k_{n-1}+0\)

    \(F(n)=\begin{vmatrix} f(n) & f(n-1) & k_n \end{vmatrix}\)

    \(base=\begin{vmatrix} 1 & 1 & 0 \\ 1 & 0 & 0 \\ 1 & 0 & 1 \end{vmatrix}\)

    带未知数 n

    \(f(n)=f(n-1)+f(n-2)+n\) ,求 \(f(n)\)

    未知数递推式 \((n)=(n-1)+1\)

    虽然只有三个转移,却需要多一个 1 来辅助 \((n)\) 得转移

    \(F(n)=\begin{vmatrix} f(n) & f(n-1) & (n) & 1 \end{vmatrix}\)

    \(base=\begin{vmatrix} 1 & 1 & 0 & 0 \\ 1 & 0 & 0 & 0 \\ 1 & 0 & 1 & 0 \\ 1 & 0 & 1 & 1 \end{vmatrix}\)

    求和

    \(f(n)=f(n-1)+f(n-2)\) ,求 \(S(n)=\sum_{i=1}^n f(i)\)

    \(S(n)=S(n-1)+f(n)\)

    \(F(n)=\begin{vmatrix} f(n) & f(n-1) & S(n-1) \end{vmatrix}\)

    \(base=\begin{vmatrix} 1 & 1 & 1 \\ 1 & 0 & 0 \\ 0 & 0 & 1 \end{vmatrix}\)



    End

  • 相关阅读:
    linux升级node版本
    mysql视图
    mysql全文本搜索
    mysql数据处理函数
    mysql数据分组
    mysql组合查询
    Django添加生产环境配置
    费用保险单,如何失焦时自动补零
    div+css滚动条
    phpadmin导入数据提示文件最大限制的修改方法
  • 原文地址:https://www.cnblogs.com/KonjakLAF/p/14151823.html
Copyright © 2020-2023  润新知