题目链接:https://ac.nowcoder.com/acm/contest/1109/A
题意理解:
给你一个(n-1)*n的矩阵,求把每一列去除后的行列式的值。
题解:
本来的想法是直接暴力枚举,然后高斯定理求行列式的值,但是算了算时间复杂度,过不去,不过还是试了试评测鸡,果然挂了!
然后想了好长时间,发现把第一行给加一个值,然后求伴随矩阵的第一行(逆矩阵的第一列)即为答案。
之后的关键在于求逆矩阵了,这里需要用到线性代数里面的知识了,可以用伴随矩阵法或者行列变化法(高斯消元),我用的是高斯消元法,关于这方面的知识可以参考这一个博客:https://blog.csdn.net/weixin_40905871/article/details/81909887
大致思想同上面的那个博客,不过有其他细节需要处理,详细过程参考代码。
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const ll mod=1e9+7;
const int maxn=205;
int a[maxn][maxn];
int b[maxn][maxn];
ll quick_mod(int a,int k)
{
ll res=1;
while(k)
{
if(k&1)res=(1ll*res*a)%mod;
a=(1ll*a*a)%mod;
k>>=1;
}
return res;
}
ll inv(int a,int p){
return quick_mod(a,p-2);
}
void Gauss(int n)
{
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
b[i][j]=(i==j);
int det=1;
for(int i=0;i<n;i++){
int t=i;
for(int k=i;k<n;k++)
if(a[k][i])
t=k;
if(t!=i)det*=-1;
for(int j=0;j<n;j++){
swap(a[i][j],a[t][j]);
swap(b[i][j],b[t][j]);
}
det=1ll*a[i][i]*det%mod;
ll Inv=inv(a[i][i],mod);
for(int j=0;j<n;j++){
a[i][j]=1ll*Inv*a[i][j]%mod;
b[i][j]=1ll*Inv*b[i][j]%mod;
}
for(int k=0;k<n;k++){
if(k==i)continue;
int tmp=a[k][i];
for(int j=0;j<n;j++){
a[k][j]=(a[k][j]-1ll*a[i][j]*tmp%mod+mod)%mod;
b[k][j]=(b[k][j]-1ll*b[i][j]*tmp%mod+mod)%mod;
}
}
}
det=(det+mod)%mod;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
b[i][j]=1ll*det*b[i][j]%mod;
}
int main(){
int n;
while(~scanf("%d",&n)){
for(int j=0;j<n;j++)
a[0][j]=2;
for(int i=1;i<n;i++)
for(int j=0;j<n;j++)
scanf("%d",&a[i][j]);
Gauss(n);
for(int i=0;i<n;i++){
if(i%2==0){
printf("%d",b[i][0]);
if(i==n-1) printf("\n");
else printf(" ");
}
else{
printf("%d",(-b[i][0]+mod)%mod);
if(i==n-1) printf("\n");
else printf(" ");
}
}
}
return 0;
}