原题:Determinant
原题大意
给出n × (n-1) 的矩阵,要求从左到右,依次去掉一列后,剩余行列式的值,同时答案mod1e9+7。
算法分析
仔细分析后发现是求伴随矩阵的原值(不要求根据行和列的奇偶改变符号),根据方阵的公式:由逆矩阵和行列式值的乘积,可以求出伴随矩阵。
所以先将矩阵补成n × n的(随机补全排除偶然性,否则可能有其他其他情况,比如不存在逆矩阵,行列式值为0),我补的是最下面一行(哪一行这个也任意)。关于求逆矩阵,先将原矩阵变成n ×(2n),并且右边是单位矩阵,将左边的变成单位矩阵,右边的就是逆矩阵。
所以这里用到了高斯消元,但是由于是mod运算,所以不能用double,加减乘要mod,除就是乘以逆元,最后得到的矩阵乘以行列式的值,最后一列就是我们要求的答案,并且根据行列的和的奇偶将值改回来,所以依次输出最后一列的值。
程序代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 202;
typedef long long ll;
const ll mod = 1e9+7;
typedef ll Matrix[maxn][maxn * 2];
int n;
ll pow_mod(ll a, ll p){
ll ans = 1;
while(p){
if(p & 1) ans = ans * a % mod;
a = a * a % mod;
p >>= 1;
}
return ans;
}
ll exgcd(ll a,ll b,ll &x,ll &y)
{
if(!b)
{
x = 1;
y = 0;
return a;
}
else
{
ll r = exgcd(b,a%b,y,x);
y -= x * (a/b);
return r;
}
}
ll lcm(ll a,ll b)
{
ll x = 0, y =0;
return a / exgcd(a,b,x,y) * b;
}
void gauss_jordan_elimination(Matrix A, int n,ll & _A){//_A是行列式的值
int i, j, k, r;
ll cnt = 0;
//变成上三角
for(i = 1; i <= n; i++){
r = i;
for(j = i+1; j <= n; j++)
if(abs(A[j][i]) > abs(A[r][i])) r = j;
//cnt记录交换次数
if(r != i) {cnt++;for(j = 1; j <= n*2; j++) swap(A[r][j], A[i][j]);}
for(k = i+1; k <= n; k++)if(A[k][i]){
ll d = lcm(A[k][i],A[i][i]);
ll t1 = d/A[k][i], t2 = d/A[i][i];
ll inv = pow_mod(t1,mod-2);
for(j = i; j <= n*2; j++) {A[k][j] = ((A[k][j] * t1- A[i][j] * t2)%mod + mod) % mod; A[k][j] = (A[k][j]*inv) % mod;}
}
}
_A = 1;
for(i = 1; i <= n; i++)
_A = (_A*A[i][i]) % mod;
if(cnt % 2 == 1) _A = mod - _A;
//变成单位矩阵
for(i = n; i >= 1; i--){
ll inv = pow_mod(A[i][i],mod-2);
for(j = i; j <= n*2; j++)
A[i][j] = (A[i][j] * inv) % mod;
if(i < n){
for(j = i+1; j <= n; j++){
ll t = A[i][j];
for(k = j; k <= n*2; k++)
{
A[i][k] = ((A[i][k] - t * A[j][k])%mod+mod)%mod;
}
}
}
}
}
int main(){
//freopen("input.txt", "r", stdin);
ios::sync_with_stdio(false);
cin.tie(0);
Matrix A;
srand((unsigned int )time(NULL));
while(cin >> n){
memset(A,0,sizeof(A));
for(int i = 1; i <= n-1; i++)
for(int j = 1; j <= n; j++)
cin >> A[i][j];
for(int j = 1; j <= n; j++)
A[n][j] = rand()%maxn;
for(int i = 1; i <= n; i++)
A[i][n+i] = 1;
ll _A;
gauss_jordan_elimination(A,n,_A);
for(int i = 1; i <= n; i++)
{
ll t = A[i][2*n] * _A;
if((i+n)%2 == 1) cout << (mod-(t%mod)) % mod;
else
cout << t % mod;
if(i!=n) cout << " ";
}
cout << endl;
}
return 0;
}