矩阵乘法学习笔记(一)

http://www.matrix67.com/blog/archives/276
先丢马大,镇笔记

一、矩阵的计算

矩阵的加法与乘法本人就不在此赘述了,这里描述一下对于矩阵乘法与矩阵加法的优化。

对于矩阵乘法。
我们需要先知道 矩阵是满足结合率的
也就是说 A*B*C==A*(B*C)
这其实非常好证明,你将整个矩阵式子打开会发现就是乘法的结合律。

那么假如我们要求A^k,即A的k次幂。
那我们就会想,能否用快速幂进行加速,事实上是可以的。
假如k=10的话
A^10=A*A*A*A*A*A*A*A*A*A
通过分配率
A^10=A^8*A^2
那么就会发现,这与快速幂是一样的,那么便可以用快速幂加速。

对于矩阵加法。
假如说要求A^1+A^2+A^3+…+A^k的和
假如A是一个n*n的矩阵
对于暴力的复杂度为O(n^2k)
但是我们会发现假如A是一个数的话,那么求的是一个等比数列的和,那么根据高中数学数列的知识。
显然
A^1+A^2+A^3+A^4等价于A^1+A^2+A^2*(A^1+A^2)=(1+A^2) <script type="math/tex" id="MathJax-Element-40">*</script>(A^1+A^2)
这实际上就是一个二分
题目链接

http://poj.org/problem?id=3233

附上个人很丑的代码,代码中的^重载即是快速幂

#include<bits/stdc++.h>
#define fer(i,j,n) for(int i=j;i<=n;i++)
#define far(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
const int maxn=1010;
const int INF=1e9+7;
using namespace std;
/*----------------------------------------------------------------------------*/
inline ll read()
{
    char ls;ll x=0,sng=1;
    for(;ls<'0'||ls>'9';ls=getchar())if(ls=='-')sng=-1;
    for(;ls>='0'&&ls<='9';ls=getchar())x=x*10+ls-'0';
    return x*sng;
}
/*----------------------------------------------------------------------------*/
int n,k,mod,num;
struct kaga
{
    ll v[31][31];
    kaga friend operator *(kaga a,kaga b)
    {
        kaga c;
        fer(i,1,n)
            fer(j,1,n)
            {
                c.v[i][j]=0;    
                fer(k,1,n)
                c.v[i][j]=(c.v[i][j]+a.v[i][k]*b.v[k][j])%mod;
            }
        return c;
    }
    kaga friend operator +(kaga a,kaga b)
    {
        fer(i,1,n)
            fer(j,1,n)
                a.v[i][j]=(a.v[i][j]+b.v[i][j])%mod;
        return a;
    }
    kaga friend operator ^(kaga a,int k)
    {
        kaga ans;
        fer(i,1,n)
            fer(j,1,n)if(i==j)ans.v[i][j]=1;
        for(;k;k>>=1,a=a*a)
            if(k&1)ans=ans*a;
        return ans; 
    }
    void friend print(kaga a)
    {
        fer(i,1,n)
        {
            fer(j,1,n)
            cout<<a.v[i][j]%mod<<" ";
            cout<<endl;
        }
    }
}a,b,ans;
kaga solve(kaga a,int k)
{
    if(k==1)return a;
    if(k&1)
    {
        kaga c=solve(a,k>>1);
        k++;k>>=1;
        kaga d=a^k;
        return (d+b)*c+d;
    }
    else
    {
        kaga c=solve(a,k>>1);
        k>>=1;
        return ((a^k)+b)*c;
    }
}
int main()
{
    n=read();k=read();mod=read();
    fer(i,1,n)
        fer(j,1,n)
        {
            if(i==j)b.v[i][j]=1;
            else b.v[i][j]=0;
            a.v[i][j]=read()%mod;
        }
    ans=solve(a,k);
    print(ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值