抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

根据线性代数里面的做法,我们构造一个增广矩阵 [A,E][A,E],两端施加一个操作 PP,当 [PA,PE]=[E,PE][PA,PE]=[E,PE] 的时候,PP 就是 E1E^{-1}。我们可以通过矩阵的初等行变换完成上述的内容,核心就是 1. 交换两行,2. 把一行的 kk 倍加到另一行 还有一种操作不属于矩阵的初等行变换,就是一行乘以一个常数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include <bits/stdc++.h>
#define MAXN 1005
#define MOD 1000000007
using namespace std;
inline int read(){
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
int a[MAXN][MAXN*2];
int n;
int ksm(int b,int k){
int res=1;
while(k){
if(k&1) res=1LL*res*b%MOD;
b=1LL*b*b%MOD;
k>>=1;
}
return res;
}
int rev(int b){
return ksm(b,MOD-2);
}
namespace Gauss_Inv{
void Gauss(){
for (int i=1;i<=n;++i){//将第i行看成主元
int r=i;
for (int j=i+1;j<=n;++j){
if (abs(a[j][i])>abs(a[r][i])) r=j;
}
for (int j=1;j<=n*2;++j) swap(a[i][j],a[r][j]);//交换的操作是为了尽可能让 a[i][i]=0
if (a[i][i]==0){//矩阵不是满秩矩阵
puts("No Solution");
exit(0);
}
int inv=rev(a[i][i]);
for (int j=1;j<=n;++j){
if (j==i) continue;
int t=1LL*a[j][i]*inv%MOD;
for (int k=1;k<=n*2;++k){
a[j][k]=(a[j][k]-1LL*a[i][k]*t%MOD+MOD)%MOD;
}
}
}
for (int i=1;i<=n;++i){
int inv=rev(a[i][i]);
for (int j=1;j<=2*n;++j){
a[i][j]=1LL*a[i][j]*inv%MOD;
}
}
}
};
using namespace Gauss_Inv;
int main(){
n=read();
for (int i=1;i<=n;++i){
for (int j=1;j<=n;++j){
a[i][j]=read();
a[i][j+n]=i==j;
}
}
Gauss();
for (int i=1;i<=n;++i){
for (int j=1;j<=n;++j){
printf("%d ",a[i][j+n]);
}
puts("");
}
return 0;
}

评论