矩阵乘法学习笔记
2015-03-16 18:39
477 查看
矩阵乘法是一种可以把递推优化到log(n)的一种算法。
矩阵乘法在运算的时候需要满足所相乘的两个矩阵的A的列数和矩阵B的行数相等时两个矩阵才可能想乘。比如一个矩阵A(2*3)和一个矩阵B(3*1)相乘可以得到一个矩阵C(2*1)的矩阵。
矩阵乘法在计算的时候满足结合律,但是不满足交换律,当我们在用矩阵乘进行计算的时候往往需要用到快速幂。
那么矩阵乘法的两项是如何运算的呢?
其实所得的矩阵的每一个位置i,j上的数就是矩阵A的第i行上的n个数和矩阵B的第j列上的n个数对应相乘再相加的和。
例如矩阵
和
相乘:
。
在了解了矩阵乘法的计算规则以后就可以去做题了,放一道矩阵乘法的基础题:
CODEVS1250
Fibonacci数列
题目描述 Description
定义:f0=f1=1, fn=fn-1+fn-2(n>=2)。{fi}称为Fibonacci数列。
输入n,求fn mod q。其中1<=q<=30000。
输入描述 Input Description
第一行一个数T(1<=T<=10000)。
以下T行,每行两个数,n,q(n<=109, 1<=q<=30000)
输出描述 Output Description
文件包含T行,每行对应一个答案。
样例输入 Sample Input
3
6 2
7 3
7 11
样例输出 Sample Output
1
0
10
数据范围及提示 Data Size & Hint
1<=T<=10000
n<=109, 1<=q<=30000
虽然是个斐波那契数列,但是由于数据范围的限制,我们不可以用递推来求出第n项的结果,所以我们就想到了矩阵乘法我们要求的是发 f
,但是f
是由f[n-1]+f[n-2]得来的,所以我们可以建立这样的两个矩阵
这样我们所得到的矩阵就变成了
至于为什么要这么做呢,是因为我们要求的f
是由f[n-1]+f[n-2]得出的,所以我们需要一个矩阵B,这样就可以得到矩阵C应该和矩阵B一样的是f
和f[n-1],所以我们就可以知道矩阵A为什么了。
我们还可以将上面的式子再一次进行转化,就可以得出最后的答案就是
的首项了。至于前面的x^(n-2)的运算,我们就可以用快速幂了。最后的答案即为所得出的第一项。
至于第0和1项就特判一下就好了。
矩阵乘法在运算的时候需要满足所相乘的两个矩阵的A的列数和矩阵B的行数相等时两个矩阵才可能想乘。比如一个矩阵A(2*3)和一个矩阵B(3*1)相乘可以得到一个矩阵C(2*1)的矩阵。
矩阵乘法在计算的时候满足结合律,但是不满足交换律,当我们在用矩阵乘进行计算的时候往往需要用到快速幂。
那么矩阵乘法的两项是如何运算的呢?
其实所得的矩阵的每一个位置i,j上的数就是矩阵A的第i行上的n个数和矩阵B的第j列上的n个数对应相乘再相加的和。
例如矩阵
和
相乘:
。
在了解了矩阵乘法的计算规则以后就可以去做题了,放一道矩阵乘法的基础题:
CODEVS1250
Fibonacci数列
题目描述 Description
定义:f0=f1=1, fn=fn-1+fn-2(n>=2)。{fi}称为Fibonacci数列。
输入n,求fn mod q。其中1<=q<=30000。
输入描述 Input Description
第一行一个数T(1<=T<=10000)。
以下T行,每行两个数,n,q(n<=109, 1<=q<=30000)
输出描述 Output Description
文件包含T行,每行对应一个答案。
样例输入 Sample Input
3
6 2
7 3
7 11
样例输出 Sample Output
1
0
10
数据范围及提示 Data Size & Hint
1<=T<=10000
n<=109, 1<=q<=30000
虽然是个斐波那契数列,但是由于数据范围的限制,我们不可以用递推来求出第n项的结果,所以我们就想到了矩阵乘法我们要求的是发 f
,但是f
是由f[n-1]+f[n-2]得来的,所以我们可以建立这样的两个矩阵
这样我们所得到的矩阵就变成了
至于为什么要这么做呢,是因为我们要求的f
是由f[n-1]+f[n-2]得出的,所以我们需要一个矩阵B,这样就可以得到矩阵C应该和矩阵B一样的是f
和f[n-1],所以我们就可以知道矩阵A为什么了。
我们还可以将上面的式子再一次进行转化,就可以得出最后的答案就是
的首项了。至于前面的x^(n-2)的运算,我们就可以用快速幂了。最后的答案即为所得出的第一项。
至于第0和1项就特判一下就好了。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define F(i,x,y) for(i=x;i<=y;++i) using namespace std; int a[2][2],ans[2][2],n,m,t,c[2][2],b[2]; int main() { scanf("%d",&t); while(t--){ int i,j,out,y; a[0][0]=ans[0][0]=1;a[0][1]=ans[0][1]=1; a[1][0]=ans[1][0]=1;a[1][1]=ans[1][1]=0; b[0]=b[1]=1; scanf("%d%d",&n,&m); if(n<=1) printf("1\n"); else{ y=n-2; while(y){ if(y&1){ c[0][0]=(a[0][0]*ans[0][0]+a[0][1]*ans[1][0])%m; c[0][1]=(a[0][0]*ans[0][1]+a[0][1]*ans[1][1])%m; c[1][0]=(a[1][0]*ans[0][0]+a[1][1]*ans[1][0])%m; c[1][1]=(a[1][0]*ans[0][1]+a[1][1]*ans[1][1])%m; F(i,0,1) F(j,0,1) ans[i][j]=c[i][j]; } y>>=1; c[0][0]=(a[0][0]*a[0][0]+a[0][1]*a[1][0])%m; c[0][1]=(a[0][0]*a[0][1]+a[0][1]*a[1][1])%m; c[1][0]=(a[1][0]*a[0][0]+a[1][1]*a[1][0])%m; c[1][1]=(a[1][0]*a[0][1]+a[1][1]*a[1][1])%m; F(i,0,1) F(j,0,1) a[i][j]=c[i][j]; } out=(ans[0][0]*b[0]+ans[0][1]*b[1])%m; printf("%d\n",out); } } }
相关文章推荐
- 「矩阵乘法」学习笔记
- 009-矩阵乘法-分治法-《算法设计技巧与分析》M.H.A学习笔记
- 线性代数的本质学习笔记(2):矩阵乘法与线性变换复合
- 矩阵乘法学习笔记(二)(vijos1049+vijos1067)
- 3D数学与线性代数学习笔记之 ——深刻理解矩阵乘法
- Python2.7学习笔记-矩阵乘法matrix vs. ndarray ; dot vs. inner,
- 基于hadoop的矩阵乘法(学习笔记)
- POJ3070 Fibonacci[矩阵乘法]【学习笔记】
- R语言里的矩阵处理学习笔记
- Python学习笔记(四)99乘法表(for)
- RADASM学习笔记【1】-- 乘法学习
- 【狂人C】学习笔记之一个简单的乘法函数的应用
- opencv学习笔记[9]:Opencv的基本数据类型和矩阵结构
- Java学习笔记13:输出26个字母矩阵
- 向量 矩阵 学习笔记1
- (算法学习)矩阵乘法及其应用
- 矩阵论学习笔记之一矩阵的约当标准形
- C++/GDI+ 学习笔记(五)——实用技巧——颜色矩阵(ColorMatrix)
- 【转】C++/GDI+ 学习笔记(四)——实用技巧——颜色矩阵(ColorMatrix)
- 矩阵乘法,留待熟悉一下类再学习。