也许你只是不小心点入了此博客,为了不眛自己的良心,首先我们会介绍什么是矩阵。
在数学中,矩阵(Matrix)是一个按照长方阵列排列的实数或复数集合,最早来自于方程组的系数及常数所构成的方阵。
由m×n个数aij排成的m行n列的数表称为m行n列的矩阵,简称m×n矩阵。记作:
而矩阵中的各个元素就是元。
元素是实数的矩阵称为实矩阵,元素是复数的矩阵称为复矩阵。而行数与列数都等于n的矩阵称为n阶矩阵或n阶方阵。n阶方阵中所有i=j的元素aij组成的斜线称为(主)对角线,所有i+j=n+1的元素aij组成的斜线称为辅对角线。
矩阵的加法就是两个同行同列的矩阵中的各个对应元素相加,即;
当然加法也适用运算律。
交换律:;
结合律:;
矩阵的减法与加法类似,也是两个同行同列的矩阵中的各个对应元素相减,即;
矩阵的数乘就是一个矩形中的每个元素与数相乘,即;
数乘也有运算律:
分配律:;
结合律:;
矩阵的转置就是一个矩阵的行转成列,列转成行,即:
而矩阵的运算还有共轭和共轭转置,在此就不必多讲。
也许你会看到题目会有些迷惑,为什么还要讲矩阵的乘法,数乘不就是吗?
开始我也是十分的迷。
现在我才知道这是矩阵乘以矩阵。
但是该怎么算呢?
两个矩阵的乘法仅当第一个矩阵A的列数和第二个矩阵B的行数相等时才能定义(做乘法)。如A是m×n矩阵,B是n×p矩阵,它们的乘积C是一个m×p矩阵C=(cij),它的任意一个元素值为:
矩阵的乘法运算满足结合律、左分配率、右分配律,但是不满足交换律。即:
(AB)C=A(BC),
(A+B)C=AC+BC,
C(A+B)=CA+CB,
AB不一定能BA(除非行列完全一样)。
而代码就有两种了:
朴素法:
#include
#include
int an,a[105][105],b[105][105],c[105][105],am,bn,bm;
int main()
{
scanf("%d%d",&an,&am);
for(int i=1;i<=an;i++)
for(int j=1;j<=am;j++)
scanf("%d",&a[i][j]);
bn=am;
scanf("%d",&bm);
for(int i=1;i<=bn;i++)
for(int j=1;j<=bm;j++)
scanf("%d",&b[i][j]);
for(int i=1;i<=an;i++)
for(int j=1;j<=bm;j++)
for(int k=1;k<=am;k++)
c[i][j]+=a[i][k]*b[k][j];
}
结构体重载运算符法(装B法):
node operator*(const node &a)
{
node r;
r.n=n;
r.m=a.m;
for(int i=1;i<=r.n;i++)
for(int j=1;j<=r.m;j++)
for(int k=1;k<=m;k++)
r.c[i][j]=(r.c[i][j]+(c[i][k]*a.c[k][j])%mod)%mod;
return r;
}
一个n×n的方阵A的行列式记为det(A)或者|A|,一个2×2矩阵的行列式可表示如下:
把一个n阶行列式中的元素aij所在的第i行和第j列划去后,留下来的n-1阶行列式叫做元素aij的余子式,记作Mij。记Aij=(-1)i+jMij,叫做元素aij的代数余子式。例如:
一个n×n矩阵的行列式等于其任意行(或列)的元素与对应的代数余子式乘积之和,即:
输入n,m。
5 1000
5
由题目我们可知,这一题使用的是矩阵加速,而矩阵加速究竟是个什么东西?
我们首先要知道 矩阵A × 矩阵B = 矩阵C,矩阵C一定是A的行B的列;如果我们构造一个矩阵B,它的行列数恰好是矩阵A列数的方阵,那么矩阵C的行列数一定和矩阵A完全一样!
比如:矩阵A是(m行n列),矩阵B是(n行n列),那么相乘之后,矩阵C一定是(m行n列)。
那我们就可以构造A,B矩阵来求答案了。
再用快速幂就可以求出答案,答案在A[1][2];
代码实现:
#include
#include
#include
#include
using namespace std;
#define ll long long
ll n1,mod;
struct node{
ll n,m,c[10][10];
node ()
{
memset(c,0,sizeof(c));
}
node operator*(const node &a)
{
node r;
r.n=n;
r.m=a.m;
for(int i=1;i<=r.n;i++)
for(int j=1;j<=r.m;j++)
for(int k=1;k<=m;k++)
r.c[i][j]=(r.c[i][j]+(c[i][k]*a.c[k][j])%mod)%mod;
return r;
}
}b,f1;
node qkpow(node a,ll p)
{
node res;
res.n=res.m=2;
for(int i=1;i<=res.n;i++)
res.c[i][i]=1;
while(p)
{
if(p&1)
res=res*a;
a=a*a;
p/=2;
}
return res;
}
int main()
{
scanf("%lld%lld",&n1,&mod);
b.n=2;
b.m=2;
b.c[1][2]=1;
b.c[2][1]=1;
b.c[2][2]=1;
node t;
t=qkpow(b,n1-2);
f1.n=1;
f1.m=2;
f1.c[1][1]=1;
f1.c[1][2]=1;
f1=f1*t;
printf("%lld",f1.c[1][2]);
}