矩阵乘法在OI历程中占据了极其重要的地位
而且也很好用~~
矩阵乘法的定义
我们定义
A[x,y]∗B[y,z]=C[x,z]
为
Ci,j=∑k=1yAi,k⋅Bk,j
非常简单,可以看出 朴素相乘的复杂度是 O(xyz) 的
//然而,暂时我还不了解更简单的办法
二进制矩阵
呃,简单地说,就是将乘法换成and(与运算),加法换成xor(异或)
矩阵乘法的性质
- 满足结合律即(A∗B)∗C=A∗(B∗C)
- 不满足交换律即A∗B∗C≠C∗B∗A,严谨的说,是不一定的。
通俗的讲,会出现无法进行运算的情况,还怎么交换律?
(这取决于矩阵乘法的定义) - 由(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]
表示斐波那契数列的
第i−1项
和
第i项
(取模意义下)
我们的目标是,将矩阵A和其他矩阵相乘,做到每次使i+1(即多推一位)
我们再引用一个矩阵
友矩阵B[2,2]
,适当构建B,使A*B刚好推后了一位。
怎么构建呢?
还是留给大家想想吧。
然而这还不够,尤其是时间
由满足结合律即(A∗B)∗C=A∗(B∗C)可得,它可以运用快速幂
∵ans=A∗B∗B∗⋅⋅⋅∗B
∴ans=A∗Bn
提供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.