【总结】矩阵乘法

                                                 矩阵乘法

       矩阵乘法公式:

       模板(LOJ100):

#include <bits/stdc++.h>
using namespace std;

const int Max=501;
const int mod=1000000007;
int n,m,p;
int a[Max][Max],b[Max][Max],c[Max][Max];

inline int get_int()
{
	int x=0,f=1;
	char c;
	for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar());
	if(c=='-') {f=-1;c=getchar();}
	for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
	return x*f;
}

int main()
{
	n=get_int(),p=get_int(),m=get_int();
	for(int i=1;i<=n;i++) 
	  for(int j=1;j<=p;j++) a[i][j]=get_int();
	for(int i=1;i<=p;i++)
	  for(int j=1;j<=m;j++) b[i][j]=get_int();
	for(int i=1;i<=n;i++)
	  for(int j=1;j<=m;j++)
	    for(int k=1;k<=p;k++)
	      c[i][j] = (c[i][j] + (long long)a[i][k] * b[k][j]) % mod;
	for(int i=1;i<=n;i++)
	{
	  for(int j=1;j<=m;j++) cout<<(c[i][j] % mod +mod) % mod<<" ";
	  cout<<"\n";
 	}

 	return 0;
}

一.斐波拉契系列问题

1.POJ3070

解析:

       大概意思就是求Fibonacci数列第N项。

       建一个2*2的矩阵A:

       0     1

       1     1

       然后把我们每次存的两个数放在另一个矩阵B里面:

       f[ n - 1 ]    f[ n ]

       那么把这两个矩阵相乘就可以得到另一个矩阵:

       f[ n ]    f[ n + 1 ]

       所以初始化矩阵{f[ 0 ],f[ 1 ]},第N项即为矩阵A的N次方乘以初始矩阵,用矩阵快速幂实现。
 

代码:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cstring>
using namespace std;

const int mod=10000;
int n;

inline void mul(int a[2][2],int f[2])
{
	int c[2];
	memset(c,0,sizeof(c));
	for(int i=0;i<2;i++)
	    for(int k=0;k<2;k++)
	      c[i] = (c[i] + (long long)a[k][i] * f[k]) % mod;
	memcpy(f,c,sizeof(c));
}

void mulself(int a[2][2]) {
	int c[2][2];
	memset(c, 0, sizeof(c));
	for (int i = 0; i < 2; i++)
		for (int j = 0; j < 2; j++)
			for (int k = 0; k < 2; k++)
				c[i][j] = (c[i][j] + (long long)a[i][k] * a[k][j]) % mod;
	memcpy(a, c, sizeof(c));
}

int main()
{
	while(scanf("%d",&n)!=EOF)
	{
	  if(n==-1) break;
	  int a[2][2] = {{0,1},{1,1}},f[2]={0,1};
	  while(n)
	  {
	  	if(n&1) mul(a,f);
	  	n>>=1;
	  	mulself(a);
	  }
	  cout<<f[0]<<"\n";
	}

	return 0;
}

2.LOJ10221

解析:

       跟上一道题的思路相似,构造矩阵A:

       1    0    0

       1    1    1

       0    1    0

       再建一个矩阵B:

       s[ n - 1 ]    f[ n ]    f[ n - 1 ]。

       那么把这两个矩阵相乘就可以得到另一个矩阵:

       s[ n ]    f[ n + 1 ]    f[ n ]。

       然后矩阵快速幂。

代码:

#include <bits/stdc++.h>
using namespace std;
int n,m;
int a[3][3] = {{1,0,0},{1,1,1},{0,1,0}},b[3]={1,1,1};
inline int get_int()
{
	int x=0,f=1;
	char c;
	for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar());
	if(c=='-') {f=-1;c=getchar();}
	for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
	return x*f;
}
inline void mul()
{
	int c[3];
	memset(c,0,sizeof(c));
	for(int j=0;j<3;j++)
	  for(int k=0;k<3;k++) c[j] = (c[j] + (long long)b[k] * a[k][j]) % m;
	memcpy(b,c,sizeof(c));
}
inline void mulself()
{
	int c[3][3];
	memset(c,0,sizeof(c));
	for(int i=0;i<3;i++)
	  for(int j=0;j<3;j++)
	    for(int k=0;k<3;k++) c[i][j] =(c[i][j] + (long long)a[i][k] * a[k][j]) % m;
	memcpy(a,c,sizeof(c));
}
int main()
{
	n=get_int(),m=get_int();
	n--;
	while(n)
	{
	  if(n&1) mul();
	  n>>=1;
	  mulself();
	}
	cout<<b[0]<<"\n";
	return 0;
}

二.综合应用

1.BZOJ1009

解析

2.BZOJ1297

解析

总结:

       矩阵乘法一大特点就是能加速递推,再log级别的复杂度内解决问题,常用于递推与DP,其难点在于构造出矩阵。

猜你喜欢

转载自blog.csdn.net/m0_38083668/article/details/81570463
今日推荐