zoukankan      html  css  js  c++  java
  • 矩陣乘法

    以前学过的,现在忘了 居然没有做过笔记

    又得再学一遍2333

    定义

    与数学上矩阵乘法相同

    如下 (A)是一个 (n*m)的矩阵

    [A=left[ egin{matrix} a_{1,1} & a_{1,2} & a_{1,3}&...a_{1,m} \ a_{2,1} & a_{2,2} & a_{2,3}&...a_{2,m} \ ...& ...&...&...\ a_{n,1} & a_{n,2} & a_{n,3}&...a_{n,m} end{matrix} ight] ]

    如下 (B)是一个 (m*p)的矩阵

    [B=left[ egin{matrix} b_{1,1} & b_{1,2} & b_{1,3}&...b_{1,p} \ b_{2,1} & b_{2,2} & b_{2,3}&...b_{2,p} \ ...& ...&...&...\ b_{m,1} & b_{m,2} & b_{m,3}&...b_{m,p} end{matrix} ight] ]

    如下 (C=A*B (n*p))

    [C=left[ egin{matrix} displaystylesum_{i=1}^{m}a_{1,i}*b_{i,1}& c_{1,2} & c_{1,3}&...c_{1,p} \ c_{2,1} & c_{2,2} & c_{2,3}&...c_{2,p} \ ...& ...&...&...\ c_{m,1} & c_{m,2} & c_{m,3}&...c_{m,p} end{matrix} ight] ]

    可知

    [c_{i,j} = displaystylesum_{k=1}^{m}a_{i,k}*b_{k,j} ]

    实现

    struct matrix
    {
    	ll n,m,c[MAXN][MAXN];
    	matrix operator *(matrix &B) const
    	{
    		matrix C;
    		C.n = n,C.m = B.m;
    		for(reg i = 1;i <= n;i++)
    			for(reg k = 1;k <= B.m;k++)
    			{
    				C.c[i][k] = 0;
    				for(reg j = 1;j <= m;j++)
    						C.c[i][k] = (C.c[i][k] + c[i][j] * B.c[j][k]) % mod;	
    			}
    		return C;
    	}
    	void pr()
    	{
    		for(reg i = 1;i <= n;i++)
    		{
    			for(reg j = 1;j <= m;j++)
    			{
    				printf("%d ",c[i][j]);
    			}
    			putchar('
    ');
    		}
    		putchar('
    ');
    	}
    };
    

    用途

    加快(dp)

    例如 P1962 斐波那契数列

    动态规划方程为
    
    dp[i] = dp[i - 1] + dp[i - 2]
    

    求 第(n)

    先画个矩阵

    [left[ egin{matrix} 0&1\ 1&1\ end{matrix} ight] ]

    [left[ egin{matrix} dp[i]&dp[i + 1]\ end{matrix} ight] ]

    (displaystyleRightarrow^{A*B})

    [left[ egin{matrix} dp[i+1]&d[i+2]\ end{matrix} ight] ]

    看到这里 就明白了了

    但是这样 时间并没有减少啊

    (Attention)

    矩阵乘法满足交换律

    [A*B*C=A*(B*C) ]

    那么

    [left[ egin{matrix} 0&1\ 1&1\ end{matrix} ight] ]

    可以使用矩阵快速幂了!!

    构建 一个矩阵(B)

    (S.T.A*B=A)

    在这道题中

    [B=left[ egin{matrix} 1&0\ 0&1\ end{matrix} ight] ]

    inline matrix qkpow(matrix A,ll n)
    {
    	matrix res;
    	res.n = res.m = 2,res.c[1][1] = res.c[2][2] = 1;
    	res.c[1][2] = res.c[2][1] = 0;
    	while(n)
    	{
    		if(n & 1) res = res * A;
    		n >>= 1;
    		A = A * A;
    	}
    	return res;
    }
    

    (Code)

    #include <cmath>
    #include <cstdio>
    #include <climits>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    #define isdigit(x) ('0' <= (x)&&(x) <= '9')
    #define reg register int
    template<typename T>
    inline T Read(T Type)
    {
    	T x = 0;
    	bool f = 0;
    	char a = getchar();
    	while(!isdigit(a)) {if(a == '-') f = 1;a = getchar();}
    	while(isdigit(a)) x = (x << 1) + (x << 3) + a - '0',a = getchar();
    	if(f) x *= -1;
    	return x;
    }
    typedef long long ll;
    const int MAXN = 100,mod = 1000000007;
    struct matrix
    {
    	ll n,m,c[MAXN][MAXN];
    	matrix operator *(matrix &B) const
    	{
    		matrix C;
    		C.n = n,C.m = B.m;
    		for(reg i = 1;i <= n;i++)
    			for(reg k = 1;k <= B.m;k++)
    			{
    				C.c[i][k] = 0;
    				for(reg j = 1;j <= m;j++)
    						C.c[i][k] = (C.c[i][k] + c[i][j] * B.c[j][k]) % mod;	
    			}
    		return C;
    	}
    	void pr()
    	{
    		for(reg i = 1;i <= n;i++)
    		{
    			for(reg j = 1;j <= m;j++)
    			{
    				printf("%d ",c[i][j]);
    			}
    			putchar('
    ');
    		}
    		putchar('
    ');
    	}
    };
    inline matrix qkpow(matrix A,ll n)
    {
    	matrix res;
    	res.n = res.m = 2,res.c[1][1] = res.c[2][2] = 1;
    	res.c[1][2] = res.c[2][1] = 0;
    	while(n)
    	{
    		if(n & 1) res = res * A;
    		n >>= 1;
    		A = A * A;
    	}
    	return res;
    }
    int main()
    {
    	ll n = Read(1ll); n -= 1;
    	matrix A,B;
    	A.n = 1,A.m = 2,A.c[1][1] = A.c[1][2] = 1;
    	B.n = B.m = 2,B.c[1][1] = 0,B.c[1][2] = B.c[2][1] = B.c[2][2] = 1;
    	matrix C = qkpow(B,n);
    	A = A * C;
    	printf("%lld",A.c[1][1]);
    	return 0;
    }
    
  • 相关阅读:
    nginx的安装及简单负载均衡配置
    memcached 的配置及 spymemcached 客户端简单使用
    我的github地址
    学习3ds max插件开发过程中的一些小结
    编译opengl编程指南第八版示例代码通过
    lua执行字节码的过程介绍
    lua解析赋值类型代码的过程
    lua解析脚本过程中的关键数据结构介绍
    lua解释执行脚本流程
    lua中的string类型
  • 原文地址:https://www.cnblogs.com/resftlmuttmotw/p/11747193.html
Copyright © 2011-2022 走看看