{算法}矩阵乘法

矩阵乘法在OI历程中占据了极其重要的地位
而且也很好用~~

矩阵乘法的定义

我们定义 A[x,y]B[y,z]=C[x,z]

Ci,j=k=1yAi,kBk,j

非常简单,可以看出 朴素相乘的复杂度是 O(xyz)
//然而,暂时我还不了解更简单的办法

二进制矩阵

呃,简单地说,就是将乘法换成and(与运算),加法换成xor(异或)

矩阵乘法的性质


  1. 满足结合律即(A∗B)∗C=A∗(B∗C)
  2. 不满足交换律即A∗B∗C≠C∗B∗A,严谨的说,是不一定的。
    通俗的讲,会出现无法进行运算的情况,还怎么交换律?
    (这取决于矩阵乘法的定义)
  3. 由(1)可得,它可以运用快速幂

作为一个蒟蒻,我能做的是给你们 这个网址(至少我没有看懂)

矩阵乘法的作用

让我们先来看一道题目

斐波那契数列
 大家都知道斐波那契数列,其中F(1)=0,F(2)=1,F(N)=F(N-1)+F(N-2)(N>=3),输入N(1<=N<=10^9),计算F(N)mod 100000007的值

方法很简单,计算 Fn ,然后取模

那么问题来了

How can you compute the answer to this question?
简单地套公式显然不会对,我们考虑运用矩阵乘法解决这道题。

我们定义矩阵 A[1,2] 表示斐波那契数列 i1 i (取模意义下)
我们的目标是,将矩阵A和其他矩阵相乘,做到每次使i+1(即多推一位)
我们再引用一个矩阵 B[2,2] ,适当构建B,使A*B刚好推后了一位。
怎么构建呢?
还是留给大家想想吧。
然而这还不够,尤其是时间

满足结合律即(A∗B)∗C=A∗(B∗C)可得,它可以运用快速幂
ans=ABBB
ans=ABn

提供Code

const
        moder=100000007;
type
        matrix=array[1..2,1..2] of int64;
var
        n:longint;
        a,b:matrix;
        i,j,l:longint;
function matr(a,b:matrix):matrix;//表示A*B
var
        c:matrix;
        i,j,l:longint;
begin
        for i:=1 to 2 do
        for j:=1 to 2 do
        begin
                c[i,j]:=0;
                for l:=1 to 2 do
                        c[i,j]:=(c[i,j]+(a[i,l]*b[l,j]))mod moder;
        end;
        exit(c);
end;
function qsm(x:matrix;y:longint):matrix;//快速幂(矩阵版)
var
        c:matrix;
begin
        if y=1 then exit(x);
        if y=0 then
        begin
                c[1,1]:=1;c[1,2]:=0;
                c[2,1]:=0;c[2,2]:=1;
                //此处c相当于1
                exit(c);
        end;
        if(y shr 1=0)then
                exit(qsm(x,y and 1))
        else
        if(y shr 1=1)and(y and 1=0)then
                exit(matr(x,x))
        else
        if(y shr 1=1)then
                exit(matr(qsm(x,2),qsm(x,y and 1)))
        else
        if(y and 1=0)then
                exit(qsm(qsm(x,y shr 1),2))
        else
                exit(matr(qsm(qsm(x,y shr 1),2),qsm(x,y and 1)));
end;
begin
        b[1,1]:=0;b[1,2]:=1;
        b[2,1]:=1;b[2,2]:=1;
        readln(n);
        a:=qsm(b,n-2);
        writeln(a[2,2]);
        close(input);close(output);
end.

你可能感兴趣的:({算法}矩阵乘法)