#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<iomanip>
#include<sstream>
#include<cmath>
#include<regex>
#define N 100
using namespace std;
template<typename out_type, typename in_value>
out_type convert(const in_value & t){
stringstream stream;
stream<<t;//向流中传值
out_type result;//这里存储转换结果
stream>>result;//向result中写入值
return result;
}
struct Number{
int x, y;
static int gcd(int a, int b){
return b==0 ? a : gcd(b, a%b);
}
Number(){}
Number(int xx, int yy=1):x(xx), y(yy){}
Number operator /(Number tmp){
return Number(x*tmp.y/(gcd(x*tmp.y, y*tmp.x)), y*tmp.x/gcd(x*tmp.y, y*tmp.x));
}
Number operator *(Number tmp){
return Number(x*tmp.x/gcd(x*tmp.x, y*tmp.y), y*tmp.y/gcd(x*tmp.x, y*tmp.y));
}
Number operator -(Number tmp){
int lcm = y*tmp.y/gcd(y, tmp.y);//最小公倍数
int xx = lcm/y*x - lcm/tmp.y*tmp.x;
if(xx==0)
return Number(0, 1);
return Number(xx/gcd(xx, lcm), lcm/gcd(xx, lcm));
}
bool operator ==(Number tmp){
return x==tmp.x && y==tmp.y;
}
};
ostream& operator<<(ostream& output, const Number &p){
output<<setw(10)<<convert<string>(p.x)+"/"+convert<string>(p.y)<<" ";
}
struct Determinant{
Number d[N][N];
int n, m;
Determinant(int nn, int mm): n(nn), m(mm){}
void out_matrix(){
for(int i=1; i<=n; ++i){
for(int j=1; j<=m; ++j)
cout<<d[i][j];
cout<<endl;
}
}
void inverse_matrix_company(Number k){
for(int i=1; i<=n; ++i)
for(int j=1; j<=m; ++j)
d[i][j] = d[i][j]/k;
}
bool exchangeRow(int mm, Number x[][N], int r){
int row = r;
for(int j=r+1; j<=n; ++j)
if(!(x[j][r]==Number(0,1))){
row = j;
break;
}
if(row != r){//交换两行
for(int j=1; j<=mm; ++j){
Number tmp = x[r][j];
x[r][j] = x[row][j];
x[row][j] = tmp;
}
return true;
}
return false;
}
Number determinantValue(){
if(n != m)
return Number(0, 1);
Number ans(1, 1);
Number dd[N][N];
for(int i=1; i<=n; ++i)
for(int j=1; j<=m; ++j)
dd[i][j] = d[i][j];
bool sign = true;
for(int i=1; i<=n; ++i){
for(int j=i+1; j<=n; ++j){
if(dd[i][i]==Number(0, 1)){
if(!exchangeRow(n, dd, i)) return Number(0, 1);
sign = !sign;
}
Number mul = dd[j][i]/dd[i][i];
for(int k=i; k<=n; ++k)
dd[j][k] = dd[j][k]-mul*dd[i][k];
}
}
for(int i=1; i<=n; ++i)
ans = ans*dd[i][i];
if(!sign) ans.x = -ans.x;
return ans;
}
Determinant inverse_matrix(){
Determinant inverse(n, m);
for(int i=1; i<=n; ++i){
for(int j=1; j<=n; ++j)
inverse.d[i][j] = d[i][j];
for(int j=n+1; j<=2*n; ++j)
inverse.d[i][j] = j-i == n ? Number(1, 1) : Number(0, 1);
}
for(int i=1; i<=n; ++i){
if(inverse.d[i][i]==Number(0,1))
exchangeRow(2*n, inverse.d, i);
if(!(inverse.d[i][i]==Number(1,1))){
Number mul = Number(1,1)/inverse.d[i][i];
for(int j=i; j<=2*n; ++j)
inverse.d[i][j] = inverse.d[i][j]*mul;
}
for(int j=i-1; j>=1; --j){
if(inverse.d[j][i]==Number(0,1)) continue;
Number mul = inverse.d[j][i]/inverse.d[i][i];
for(int k=i; k<=2*n; ++k)
inverse.d[j][k] = inverse.d[j][k]-inverse.d[i][k]*mul;
}
for(int j=i+1; j<=n; ++j){
if(inverse.d[j][i]==Number(0,1)) continue;
Number mul = inverse.d[j][i]/inverse.d[i][i];
for(int k=i; k<=2*n; ++k)
inverse.d[j][k] = inverse.d[j][k]-inverse.d[i][k]*mul;
}
}
for(int i=1; i<=n; ++i)
for(int j=1; j<=m; ++j)
inverse.d[i][j] = inverse.d[i][j+n];
return inverse;
}
Determinant company_matrix(){//伴随矩阵
Determinant company(n, m);
for(int i=1; i<=n; ++i)
for(int j=1; j<=m; ++j){
Determinant tmp(n-1, m-1);//余子式
int r=1, c=1;
for(int ii=1; ii<=n; ++ii){
c=1;
if(i!=ii){
for(int jj=1; jj<=m; ++jj)
if(j!=jj){
tmp.d[r][c] = d[ii][jj];
++c;
}
++r;
}
}
company.d[j][i] = tmp.determinantValue();//赋给伴随矩阵相应的位置
if((i+j)&1) company.d[j][i].x = -company.d[j][i].x;
}
return company;
}
};
int main(){
int n, m;
int x, y;
cin>>n>>m;
Determinant determinant(n, m);
// regex patternOne("([a-z]+)\\.([a-z]+)");
// smatch pieces_match;
for(int i=1; i<=n; ++i){
string str;
for(int j=1; j<=n; ++j){
scanf("%d/%d", &x, &y);
determinant.d[i][j] = Number(x, y);
}
}
//伴随矩阵
cout<<"伴随矩阵 "<<endl;
Determinant company = determinant.company_matrix();
company.out_matrix();
//行列式的值
// cout<<determinant.determinantValue();
// cout<<endl;
//逆置矩阵(通过伴随矩阵)
cout<<"逆置矩阵(通过伴随矩阵)"<<endl;
company.inverse_matrix_company(determinant.determinantValue());
company.out_matrix();
//逆置矩阵(初等行变换)
cout<<"逆置矩阵(初等行变换) "<<endl;
Determinant inverse = determinant.inverse_matrix();
inverse.out_matrix();
cout<<endl;
return 0;
}
/*
3
2/1 1/1 1/1
1/1 2/1 1/1
1/1 1/1 2/1
3
0/1 2/1 -1/1
1/1 1/1 2/1
-1/1 -1/1 -1/1
5
0/1 0/1 0/1 1/1 3/1
0/1 0/1 0/1 -1/1 2/1
1/1 1/1 1/1 0/1 0/1
0/1 1/1 1/1 0/1 0/1
0/1 0/1 1/1 0/1 0/1
*/