矩阵(Matrix)是一个按照长方阵列排列的集合
矩阵的加法必须保证都是同型矩阵即加减运算行列数都必须一样
矩阵的加法运算满足结合律和交换律:
A + B = B + A A+B=B+A A+B=B+A
A + ( B + C ) = ( A + B ) + C A+(B+C)=(A+B)+C A+(B+C)=(A+B)+C
减法同理
把矩阵A的行和列互相交换所产生的矩阵称为A的转置矩阵
即所有元素都乘一遍一个数
矩阵的加减法和矩阵的数乘合称矩阵的线性运算
矩阵的共轭指的是将一个复数矩阵每个元素的虚部取负,实部则不变
顾名思义,进行共轭和转制
乘法运算矩阵行数必须等于第二个矩阵的列数
a 行 b 列的矩阵 × b 行 c 列的矩阵 = a 行 c 列的矩阵 a行b列的矩阵\times b行c列的矩阵=a行c列的矩阵 a行b列的矩阵×b行c列的矩阵=a行c列的矩阵
矩阵的乘法满足结合律,不满足交换律
( a ∗ b ) ∗ c = a ∗ ( b ∗ c ) (a*b)*c=a*(b*c) (a∗b)∗c=a∗(b∗c)
e.g:
A × B = C A\times B=C A×B=C
A = ( a 1 a 2 a 3 a 4 ) A=\left( \begin{matrix} ~~a1& a2~~ \\ ~~\\ ~~a3 & a4~~ \end{matrix} \right) A= a1 a3a2 a4
B = ( b 1 b 2 b 3 b 4 ) B=\left( \begin{matrix} ~~b1& b2~~ \\ ~~\\ ~~b3 & b4~~ \end{matrix} \right) B= b1 b3b2 b4
则:
C = ( a 1 × b 1 + a 2 × b 3 a 1 × b 2 + a 2 × b 4 a 3 × b 1 + a 4 × b 3 a 3 × b 2 + a 4 × b 4 ) C=\left( \begin{matrix} ~~a1 \times b1+a2\times b3& a1\times b2+a2\times b4~~ \\ ~~\\ ~~a3\times b1+a4\times b3 & a3\times b2+a4\times b4~~ \end{matrix} \right) C= a1×b1+a2×b3 a3×b1+a4×b3a1×b2+a2×b4 a3×b2+a4×b4
行列互换
题目描述
给定两个矩阵 a , b a,b a,b,求矩阵 c = a × b c=a\times b c=a×b
输入描述
第一行四个整数 m 1 , n 1 , m 2 , n 2 m1,n1,m2,n2 m1,n1,m2,n2,代表第一个矩阵和第二个矩阵的列数和行数。
接下来 n 1 n1 n1 行,每行 m 1 m1 m1 个整数,代表第一个矩阵。
之后 n 2 n2 n2 行,每行 m 2 m2 m2 个整数,代表第二个矩阵。
数据保证 m 1 = n 2 m1=n2 m1=n2 。所有的输入数据不超过 100 100 100 。
输出描述
输出 n 1 n1 n1 行,每行 m 2 m2 m2 个整数,代表矩阵 c c c 。
样例输入1
2 2 2 2
2 2
2 2
2 2
2 2
样例输出1
8 8
8 8
样例输入2
2 2 2 2
1 2
3 1
2 5
1 7
样例输出2
4 19
7 22
#include
using namespace std;
int n1,m1,n2,m2;
int a[105][105],b[105][105],c[105][105];
void funt(){
for(int i=1;i<=n1;i++){
for(int j=1;j<=m2;j++){
for(int k=1;k<=m1;k++){
c[i][j]+=a[i][k]*b[k][j];
}
}
}
}
int main(){
scanf("%d%d%d%d",&m1,&n1,&m2,&n2);
for(int i=1;i<=n1;i++){
for(int j=1;j<=m1;j++){
scanf("%d",&a[i][j]);
}
}
for(int i=1;i<=n2;i++){
for(int j=1;j<=m2;j++){
scanf("%d",&b[i][j]);
}
}
funt();
for(int i=1;i<=n1;i++){
for(int j=1;j<=m2;j++){
printf("%d ",c[i][j]);
}
printf("\n");
}
return 0;
}
题目描述
给出两个 n n n 行 m m m 列的矩阵,求两个矩阵的和
输入描述
第一行输入两个以空格分隔的整数 n , m n,m n,m,表示矩阵的行数和列数,接下来的 n n n 行,每行 m m m 个以空格分隔的实数 T 1 [ i ] [ j ] T1[i][j] T1[i][j],表示第一个矩阵,接下来的 n n n 行,每行 m m m 个以空格分隔的实数 T 2 [ i ] [ j ] T2[i][j] T2[i][j] ,表示第二个矩阵
1 ≤ n ≤ 100 , 1 ≤ m ≤ 100 1≤n≤100,1≤m≤100 1≤n≤100,1≤m≤100
0 ≤ T 1 [ i ] [ j ] ≤ 1000 , 0 ≤ T 2 [ i ] [ j ] ≤ 1000 0≤T1[i][j]≤1000,0≤T2[i][j]≤1000 0≤T1[i][j]≤1000,0≤T2[i][j]≤1000
cout << fixed << setprecision(2) << x;
或者 printf(“%.2lf”,x);
可以用来输出小数 x x x 并保留两位小数
输出描述
输出 n n n 行,每行包含 m m m 个以空格分隔的实数,表示两个矩阵相加的结果
矩阵中的实数都保留 2 2 2 位小数
样例输入
2 3
1.1 1.2 1.3
2.1 2.2 2.3
1.1 1.2 1.3
2.1 2.2 2.3
样例输出
2.20 2.40 2.60
4.20 4.40 4.60
#include
using namespace std;
int n,m;
double a[105][105],b[105][105],c[105][105];
void funa(){
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
c[i][j]=a[i][j]+b[i][j];
}
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%lf",&a[i][j]);
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%lf",&b[i][j]);
}
}
funa();
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
printf("%.2lf ",c[i][j]);
}
printf("\n");
}
return 0;
}
如果某个元素 x x x 和其他元素 y y y 做运算,结果依旧是 y y y 那么称其为“单位元”
比如:
集合 | 运算 | 单位元 |
---|---|---|
实数 | +(加法) | 0 |
实数 | ·(乘法) | 1 |
实数 | ^(幂) | 1(只为右单位元) |
矩阵 | +(加法) | 零矩阵 |
字串 | 串接 | 空字元串 |
集合M的子集 | ∩(交集) | M |
集合 | ∪(并集) | { }(空集) |
布尔逻辑 | ∧(逻辑与) | ⊤(真值) |
布尔逻辑 | ∨(逻辑或) | ⊥(假值) |
单位矩阵就是矩阵乘法运算的单位元
单位矩阵是一种特殊的方阵,其主对角线上的元素都为 1 1 1,其他元素都为 0 0 0
以下是关于矩阵的一些功能的框架
#include
using namespace std;
struct Mat{
int a[105][105];
int r,c;
Mat(int _r=0,int _c=0){
r=_r,c=_c;
memset(a,0,sizeof a);
if(c==0)
c=r;
}
Mat operator*(const Mat t)const{
Mat ans(r,t.c);
int n=r,m=t.c;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
for(int k=1;k<=c;k++)
ans.a[i][j]+=a[i][k]*t.a[k][j];
return ans;
}
Mat operator+(const Mat t)const{
Mat ans(r,c);
for(int i=1;i<=r;i++)
for(int j=1;j<=c;j++)
ans.a[i][j]=a[i][j]+t.a[i][j];
return ans;
}
void unit(){
memset(a,0,sizeof a);
for(int i=1;i<=r;i++){
a[i][i]=1;
}
}
void print(){
for(int i=1;i<=r;i++){
for(int j=1;j<=c;j++)
cout<<a[i][j]<<" ";
}
printf("\n");
}
Mat operator %(const int t)const{
Mat ans= *this;
for(int i=1;i<=r;i++){
for(int j=1;j<=c;j++){
ans.a[i][j]%=t;
}
}
return ans;
}
Mat ksm(int x,int p){
Mat ans(r,c),a= *this;
ans.unit();
while(x){
if(x&1){
ans=ans*a%p;
}
a=a*a%p;
x>>=1;
}
return ans%p;
}
};
int main(){
return 0;
}
题目描述
求出 F n m o d 1 0 9 + 7 F_n ~mod~10^9 + 7 Fn mod 109+7 的值
输入描述
一个正整数 n ( 1 ≤ n ≤ 2 63 − 1 ) n (1≤n≤2^{63} −1) n(1≤n≤263−1)。
输出描述
输出一行一个整数表示答案。
样例输入1
5
样例输出1
5
样例输入2
10
样例输出2
55
#include
using namespace std;
long long n,mod=1e9+7;
struct Mat{
long long a[105][105];
long long r,c;
Mat(int _r=0,int _c=0){
r=_r,c=_c;
memset(a,0,sizeof a);
if(c==0)
c=r;
}
Mat operator*(const Mat t)const{
Mat ans(r,t.c);
int n=r,m=t.c;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
for(int k=1;k<=c;k++)
ans.a[i][j]+=a[i][k]*t.a[k][j];
return ans;
}
Mat operator+(const Mat t)const{
Mat ans(r,c);
for(int i=1;i<=r;i++)
for(int j=1;j<=c;j++)
ans.a[i][j]=a[i][j]+t.a[i][j];
return ans;
}
void unit(){
memset(a,0,sizeof a);
for(int i=1;i<=r;i++){
a[i][i]=1;
}
}
void print(){
for(int i=1;i<=r;i++){
for(int j=1;j<=c;j++)
cout<<a[i][j]<<" ";
}
printf("\n");
}
Mat operator %(const int t)const{
Mat ans= *this;
for(int i=1;i<=r;i++){
for(int j=1;j<=c;j++){
ans.a[i][j]%=t;
}
}
return ans;
}
Mat ksm(long long x,long long p){
Mat ans(r,c),a= *this;
ans.unit();
while(x){
if(x&1){
ans=ans*a%p;
}
a=a*a%p;
x>>=1;
}
return ans%p;
}
};
int main(){
scanf("%lld",&n);
Mat a(2,2),b(2,2);
if(n<=2){
printf("1");
return 0;
}
a.a[1][1]=a.a[1][2]=1;
b.a[1][1]=b.a[1][2]=b.a[2][1]=1;
b.a[2][2]=0;
a=a*b.ksm(n-2,mod)%mod;
printf("%lld",a.a[1][1]);
return 0;
}
题目描述
P1939 矩阵加速(数列)
#include
using namespace std;
long long n,mod=1e9+7;
struct Mat{
long long a[105][105];
long long r,c;
Mat(int _r=0,int _c=0){
r=_r,c=_c;
memset(a,0,sizeof a);
if(c==0)
c=r;
}
Mat operator*(const Mat t)const{
Mat ans(r,t.c);
int n=r,m=t.c;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
for(int k=1;k<=c;k++)
ans.a[i][j]+=a[i][k]*t.a[k][j];
return ans;
}
Mat operator+(const Mat t)const{
Mat ans(r,c);
for(int i=1;i<=r;i++)
for(int j=1;j<=c;j++)
ans.a[i][j]=a[i][j]+t.a[i][j];
return ans;
}
void unit(){
memset(a,0,sizeof a);
for(int i=1;i<=r;i++){
a[i][i]=1;
}
}
void print(){
for(int i=1;i<=r;i++){
for(int j=1;j<=c;j++)
cout<<a[i][j]<<" ";
}
printf("\n");
}
Mat operator %(const int t)const{
Mat ans= *this;
for(int i=1;i<=r;i++){
for(int j=1;j<=c;j++){
ans.a[i][j]%=t;
}
}
return ans;
}
Mat ksm(long long x,long long p){
Mat ans(r,c),a= *this;
ans.unit();
while(x){
if(x&1){
ans=ans*a%p;
}
a=a*a%p;
x>>=1;
}
return ans%p;
}
};
int main(){
int T;
Mat a(5,5);
scanf("%d",&T);
while(T--){
scanf("%lld",&n);
memset(a.a,0,sizeof(a.a));
if(n<=3){
printf("1\n");
continue;
}
a.a[1][1]=1;
a.a[3][1]=1;
a.a[1][2]=1;
a.a[2][3]=1;
a=a*a.ksm(n,mod)%mod;
printf("%lld\n",a.a[2][1]);
}
return 0;
}