• 矩阵的c++实现


    在大学数学课程《线性代数》中,就有矩阵和行列式的出现,这篇文章主要讲矩阵在c++中的实现和一些用途(目前我知道的)

    此篇文章只写c++的内容,不具体写到数学中矩阵的一些公式、性质。

    本篇文章中一部分图片来自百度百科。

    注:在编程中,习惯(不知道是不是只有我的习惯)写成n行m列矩阵,但在数学课本中,是m行n列的矩阵,不要搞混了

    一、矩阵是什么

    由 n×m 个数aij排成的n行m列的数表称为n行m列的矩阵,简称n×m矩阵。记作:

    A=\begin{bmatrix} a11,a12,a13,...,a1m \\ a21,a22,a23,...,a2m \\ a31,a32,a33,...,a3m \\ ...,...,...,...,... \\ an1,an2,an3,...,anm \end{bmatrix}

    第一次用公式不会用

    二、构建一个矩阵

    1. #include
    2. #define maxn 100
    3. using namespace std;
    4. struct Matrix{
    5. int n,m;//n行m列矩阵
    6. long long a[maxn][maxn];
    7. Matrix(){
    8. memset(a,0,sizeof a);
    9. }
    10. Matrix(int _n, int _m) {
    11. n=_n;
    12. m=_m;
    13. memset(a,0,sizeof a);
    14. }
    15. void scan(){
    16. cin>>n>>m;
    17. for(int i=0;i
    18. for(int j=0;j
    19. cin>>a[i][j];
    20. }
    21. }
    22. }
    23. void print(){
    24. for(int i=0;i
    25. for(int j=0;j
    26. cout<" ";
    27. }
    28. cout<
    29. }
    30. }
    31. };
    32. int main(){
    33. Matrix a;
    34. a.scan();
    35. a.print();
    36. return 0;
    37. }

    非常简单

    三、矩阵的运算

    1.加法

    只有m和n都相同的矩阵才可以相加。

    设C=A+B,则:

    Cij=Aij+Bij

    矩阵加法满足交换律和结合律:

    A+B=B+A

    A+(B+C)=(A+B)+C

    代码:

    1. Matrix pl(Matrix a,Matrix b){
    2. for(int i=0;i
    3. for(int j=0;j
    4. a.ma[i][j]+=b.ma[i][j];
    5. }
    6. }
    7. return a;
    8. }
    9. int main(){
    10. Matrix a,b;
    11. a.scan();
    12. b.scan();
    13. pl(a,b).print();
    14. return 0;
    15. }

    因为a会和矩阵里面的a长得很像,我就改了

    2.数乘

    就是将一个矩阵乘以一个数字

    1. Matrix mul_num(Matrix a,int b){
    2. for(int i=0;i
    3. for(int j=0;j
    4. a.ma[i][j]*=b;
    5. }
    6. }
    7. return a;
    8. }

    满足以下定律:

    结合律:a(bA)=(ab)A

    交换律:aA=Aa

    分配律:(a+b)A=aA+bA

                  (A+B)a=aA+aB

    好了,新手期度过

    3.矩阵乘法

    当A*B时,必须满足A的n(列数)和B的m(行数)相同。当A为p*n矩阵,B为n*q矩阵时,C为p*q矩阵。

    他的元素:

    1. Matrix mul(Matrix a,Matrix b){
    2. Matrix res(a.n,b.m);
    3. for(int i=0;i
    4. for(int j=0;j
    5. for(int k=0;k
    6. res.ma[i][j]+=a.ma[i][k]*b.ma[k][j];
    7. }
    8. }
    9. }
    10. return res;
    11. }

    矩阵乘法满足的运算定律:

    结合律:A(BC)=(AB)C

    左分配律:C(A+B)=CA+CB

    右分配律:(A+B)C=AC+BC

    4.单位矩阵

    我们都知道,1*a=a,那么如果我们要在矩阵中找到一个和1的性质一样的矩阵,要怎么做呢???

    单位矩阵出场!

    单位矩阵:一个n*n的矩阵,左下角到右下角都是1,其他都是0。

    当n*m的矩阵乘以一个n*n的单位矩阵时,不会发生改变。

    具体过程如下:

    \begin{bmatrix} 2,3\\ 5,6\\ 4,3 \end{bmatrix}\times \begin{bmatrix} 1 ,0 \\ 0,1 \end{bmatrix}=\begin{bmatrix} 2\times1+0,3\times1+0 \\ 5\times1+0,6\times1+0 \\ 4\times1+0,3\times1+0 \end{bmatrix}

    单位矩阵在快速幂中有用

    5.矩阵快速幂

    只有n*n矩阵才可以快速幂。

    如何快速幂???

    矩阵的快速幂和普通的不同,我们可以这样想:

    A^7=A*A*A*A*A*A*A=(A*A)*(A*A)*A*A*A

    说起来有些奇妙,但实际上就是个这样的过程:

    1. Matrix mpow(Matrix a,int n){
    2. Matrix res(a.n,a.n);
    3. for(int i=0;i1;
    4. while(n!=0){
    5. if(n&1)res=mul(res,a);
    6. a=mul(a,a);
    7. n>>=1;
    8. }
    9. return res;
    10. }

    你可能看不懂,但如果我把他变成数字的快速幂,你就懂了。

    1. int mpow(int a,int n){
    2. int res=1;//初始化
    3. while(n!=0){
    4. if(n&1)res=a*res;//统计多出来的a
    5. a=a*a;
    6. n>>=1;//就是除2
    7. }
    8. return res;
    9. }

    我们刚开始构建一个单位矩阵res,用他充当1的作用。

    6.所有运算的代码

    1. #include
    2. #define maxn 100
    3. using namespace std;
    4. int mm;
    5. struct Matrix{
    6. int n,m;
    7. long long ma[maxn][maxn];
    8. Matrix(){
    9. memset(ma,0,sizeof ma);
    10. }
    11. Matrix(int _n, int _m) {
    12. n=_n;
    13. m=_m;
    14. memset(ma,0,sizeof ma);
    15. }
    16. void scan(){
    17. cin>>n>>m;
    18. for(int i=0;i
    19. for(int j=0;j
    20. cin>>ma[i][j];
    21. }
    22. }
    23. }
    24. void print(){
    25. for(int i=0;i
    26. for(int j=0;j
    27. cout<" ";
    28. }
    29. cout<
    30. }
    31. }
    32. };
    33. Matrix pl(Matrix a,Matrix b){
    34. for(int i=0;i
    35. for(int j=0;j
    36. a.ma[i][j]+=b.ma[i][j];
    37. }
    38. }
    39. return a;
    40. }
    41. Matrix mul_num(Matrix a,int b){
    42. for(int i=0;i
    43. for(int j=0;j
    44. a.ma[i][j]*=b;
    45. }
    46. }
    47. return a;
    48. }
    49. Matrix mul(Matrix a,Matrix b){
    50. Matrix res(a.n,b.m);
    51. for(int i=0;i
    52. for(int j=0;j
    53. for(int k=0;k
    54. res.ma[i][j]+=a.ma[i][k]*b.ma[k][j];
    55. }
    56. }
    57. }
    58. return res;
    59. }
    60. Matrix mpow(Matrix a,int n){
    61. Matrix res(a.n,a.n);
    62. for(int i=0;i1;
    63. while(n!=0){
    64. if(n&1)res=mul(res,a);
    65. a=mul(a,a);
    66. n>>=1;
    67. }
    68. return res;
    69. }
    70. int main(){
    71. return 0;
    72. }

    四、矩阵在编程中的运用

    既然我们说了这么多,你可能会很疑惑:为什么我们要用到矩阵呢?编程中哪里需要用到矩阵呢?

    我学矩阵时也这样,好像矩阵离我很远的样子。

    那么我们来看几道例题:

    1.洛谷P1962斐波那契数列

    这道题用矩阵解很简单,有两种相似的做法。

    第一种做法

    我们都知道,斐波那契数列的式子是:

    F_{n}=F_{n-1}+F_{n-2}

    那我们考虑行矩阵

    \begin{bmatrix} F_{n},F_{n-1} \end{bmatrix} =\begin{bmatrix} F_{n-1},F_{n-2}\end{bmatrix}\times base

    那我们就要考虑base是什么

    分解:

    [F_{n},F_{n-1}]=[F_{n-1}+F_{n-1},F_{n-1}]

    =[1\times F_{n-1}+1\times F_{n-2},1\times F_{n-1}+0\times F_{n-2}]

    =[F_{n-1},F_{n-2}]\times \begin{bmatrix} 1,1\\ 1,0\\ \end{bmatrix}

    这不就巧了吗,刚好就出现了n-1项和n-2项,那么base就是这个1110了

    根据左分配律,可以得出,我们不断递推,就相当于

    [1,1]\times base^{n-2}

    多思考一下就可以得出了

    那么,最后只要输出就行了

    代码如下

    1. #include
    2. using namespace std;
    3. #define mod 1000000007
    4. struct Matrix{
    5. int n,m;
    6. long long a[100][100];
    7. Matrix(){
    8. memset(a,0,sizeof(a));
    9. }
    10. Matrix(int _n,int _m){
    11. n=_n;
    12. m=_m;
    13. memset(a,0,sizeof(a));
    14. }
    15. };
    16. Matrix ans(1,2);
    17. Matrix base(2,2);
    18. void init(){
    19. ans.a[0][0]=1;
    20. ans.a[0][1]=1;
    21. base.a[0][0]=1;
    22. base.a[0][1]=1;
    23. base.a[1][0]=1;
    24. base.a[1][1]=0;
    25. }
    26. Matrix mul(Matrix a,Matrix b){
    27. Matrix res(a.n,b.m);
    28. for(int i=0;i
    29. for(int j=0;j
    30. for(int k=0;k
    31. res.a[i][j]+=a.a[i][k]*b.a[k][j]%mod;
    32. }
    33. res.a[i][j]%=mod;
    34. }
    35. }
    36. return res;
    37. }
    38. Matrix bpow(Matrix a,long long n){
    39. Matrix res(2,2);
    40. for(int i=0;i<2;i++)res.a[i][i]=1;
    41. while(n!=0){
    42. if(n&1){
    43. res=mul(res,a);
    44. }
    45. a=mul(a,a);
    46. n>>=1;
    47. }
    48. return res;
    49. }
    50. long long F(long long n){
    51. base=bpow(base,n-2);
    52. ans=mul(ans,base);
    53. return ans.a[0][0]%mod;
    54. }
    55. int main(){
    56. long long n;
    57. cin>>n;
    58. if(n<=2){
    59. cout<<1;
    60. return 0;
    61. }
    62. init();
    63. cout<<F(n);
    64. return 0;
    65. }

    第二种做法

    我们换成竖的:

    \begin{bmatrix} F_{n}\\ F_{n-1}\\ \end{bmatrix}

    理论差不多,不多说了。不然又浪费我的手和时间

    应该都会了吧,自己推吧,直接上代码(因为是上课写的,格式有些不一样)

    1. #include
    2. using namespace std;
    3. const int maxn = 100 + 10;
    4. int mod;
    5. typedef long long ll;
    6. struct Matrix {
    7. int n, m;
    8. long long a[maxn][maxn];
    9. Matrix() { memset(a, 0, sizeof a); }
    10. Matrix(int _n, int _m) {
    11. n = _n;
    12. m = _m;
    13. memset(a, 0, sizeof a);
    14. }
    15. };
    16. Matrix mul(Matrix &a, Matrix &b) {
    17. Matrix res(a.n, b.m);
    18. for(int i=0;i
    19. for(int j=0;j
    20. for(int k=0;k
    21. res.a[i][j]+=a.a[i][k]*b.a[k][j]%mod;
    22. return res;
    23. }
    24. Matrix Pow(Matrix &base, ll n) {
    25. Matrix res(base.n, base.n);
    26. for(int i=0;i1;
    27. while(n!=0){
    28. if(n&1)res=mul(res,base);
    29. base=mul(base,base);
    30. n>>=1;
    31. }
    32. return res;
    33. }
    34. int main() {
    35. freopen("Fibonacci.in", "r", stdin);
    36. freopen("Fibonacci.out", "w", stdout);
    37. ll n;
    38. scanf("%lld%d", &n, &mod);
    39. if (n == 1 || n == 2) return 0 * puts("1");
    40. Matrix F(1,2);
    41. F.a[0][0]=1;
    42. Matrix A(2,2);
    43. A.a[0][0]=1;
    44. A.a[0][1]=1;
    45. A.a[1][0]=1;
    46. A.a[1][1]=0;
    47. A=Pow(A,n-1);
    48. F=mul(F,A);
    49. cout<0][0];
    50. return 0;
    51. }

  • 相关阅读:
    UE4_材质_湿度着色器及Desaturation算法_ben材质教程
    UI5 Tooling
    【错误记录】PySpark 运行报错 ( Did not find winutils.exe | HADOOP_HOME and hadoop.home.dir are unset )
    jenkins+junit4+allure+selenium实现自动化测试与结果可视化
    低代码开发浅析
    贪心算法证明问题
    微软推出Azure量子资源估算器,加速量子算法研发
    ESP8266-Arduino网络编程实例-ESP-Now-One-to-Many多设备通信
    EasyExcel表头校验方法
    【C++&Python&Java】字符处理详细解读_字符_ASCLL码_字母数字转换_算法竞赛_开发语言
  • 原文地址:https://blog.csdn.net/liudabai__/article/details/133185892