代数余子式矩阵求行列式

因为在删除一条边时矩阵只有一行上的两个值发生变化,将上述法则代入该行即可。

#include <cstdio>
#include <cmath>
#define LL long long
using namespace std;

  int n,m;
  LL sid[100001][3];
  LL tot;
  const LL mo=1e9+7;

  LL qpow(LL bas,int powe){
      LL ret=1;
      for (;powe;bas*=bas,bas%=mo){
        if (powe&1) ret*=bas,ret%=mo;
      powe=powe>>1;
    }
    return(ret);
  }

  struct matrix{
      LL a[601][601],tmp[601][601];
      int n,m;

      void cpy(matrix&b){
        n=b.n;m=b.m;
      for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++)
          a[i][j]=b.a[i][j];
    }

      void mul(matrix &b){
      for (int i=0;i<=n;i++)
        for (int j=0;j<=b.m;j++)
          tmp[i][j]=0;

      for (int i=0;i<=n;i++)
        for (int k=0;k<=m;k++)
          if (a[i][k])
            for (int j=0;j<=b.m;j++)
              tmp[i][j]+=a[i][k]*b.a[k][j]%mo,tmp[i][j]%=mo;

      for (int i=0;i<=n;i++)
        for (int j=0;j<=b.m;j++)
          a[i][j]=tmp[i][j];
      m=b.m;
    }

    LL det(){
      for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) tmp[i][j]=a[i][j];
      for (int i=1;i<=n;i++){
        for (int j=i+1;j<=n;j++){
          LL bas=a[j][i]*qpow(a[i][i],mo-2)%mo;
          for (int k=i;k<=n;k++)
            a[j][k]-=a[i][k]*bas%mo,a[j][k]%=mo,a[j][k]+=mo,a[j][k]%=mo;
          }
      }
      LL ret=1;
      for (int i=1;i<=n;i++) ret*=a[i][i],ret%=mo;
      for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) a[i][j]=tmp[i][j];
      return(ret);
    }

    void mul(LL num){
      for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++)
          a[i][j]*=num,a[i][j]%=mo;
    }

    void getinv(){
      for (int i=1;i<=n;i++) a[i][n+i]=1;
      for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) a[i][j]=(a[i][j]%mo+mo)%mo;
      for (int i=1;i<=n;i++){
        int po;LL maxi=0;
        for (int j=i;j<=n;j++){
          if (fabs(a[j][i])>maxi){
            maxi=fabs(a[j][i]);po=j;
          }
        }
        for (int j=1;j<=2*n;j++){
          LL t=a[i][j];a[i][j]=a[po][j];a[po][j]=t;
        }
        if (fabs(maxi)==0) continue;

        for (int j=i+1;j<=n;j++){
          LL tim=a[j][i]*qpow(a[i][i],mo-2)%mo;
          for (int k=i;k<=2*n;k++) a[j][k]-=a[i][k]*tim%mo,a[j][k]%=mo;
          }
        }

        for (int i=1;i<=n;i++) for (int j=1;j<=2*n;j++) a[i][j]=(a[i][j]%mo+mo)%mo;
        for (int i=n;i>=1;i--){
          for (int j=i+1;j<=n;j++){
            for (int k=n+1;k<=2*n;k++)
              a[i][k]-=a[i][j]*a[j][k]%mo,a[i][k]%=mo;
            a[i][j]=0;
          }
          for (int j=n+1;j<=2*n;j++)
            a[i][j]*=qpow(a[i][i],mo-2),a[i][j]%=mo;
          a[i][i]=1;
        }

        for (int i=1;i<=n;i++)
          for (int j=1;j<=n;j++)
            a[i][j]=(a[i][j+n]%mo+mo)%mo;
    }

    void trav(){
      for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)
          tmp[i][j]=a[j][i];
      for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)
          a[i][j]=tmp[i][j];
    }
  }a,A,inv;

  int main(){
      scanf("%d%d",&n,&m);
      a.n=a.m=n-1;
      for (int i=1;i<=m;i++){
        scanf("%lld%lld%lld",&sid[i][0],&sid[i][1],&sid[i][2]);
        a.a[sid[i][0]][sid[i][1]]--;
        a.a[sid[i][0]][sid[i][0]]++;
    }
    A.n=A.m=n-1;
    for (int i=1;i<n;i++) A.a[i][i]=1;
    A.mul(tot=a.det());

    inv.cpy(a);
    inv.getinv();
    A.mul(inv);
    A.trav();

    LL ans=0;
    for (int i=1;i<=m;i++){
      if (sid[i][0]==n) continue;
      a.a[sid[i][0]][sid[i][1]]++;
        a.a[sid[i][0]][sid[i][0]]--;
      LL ttot=0;
      for (int j=1;j<n;j++)
        ttot+=a.a[sid[i][0]][j]*A.a[sid[i][0]][j]%mo,ttot%=mo;
      ans+=(tot-ttot)*sid[i][2]%mo;ans%=mo;
      a.a[sid[i][0]][sid[i][1]]--;
        a.a[sid[i][0]][sid[i][0]]++;
    }
    printf("%lld\n",(ans%mo+mo)%mo);
  }
时间: 2024-08-08 05:15:48

代数余子式矩阵求行列式的相关文章

老笔记整理五:C实现10阶内通过展开代数余子式求行列式的值

这个分为两部分,先是写出了C实现计算三阶行列式,然后过了一段时间突然有了思路才写下了10阶内这段代码.真怀念那段写代码的日子. 一:C实现计算三阶行列式 最近高数课在上线性代数,二阶的还能口算,三阶的有点麻烦,想陆陆续续地把公式都用C来实现.因为二阶的行列式如果用C来写就是一句话:val=det[0][0]*det[1][1]-det[0][1]*det[1][0];太简单了这里就不写了,主要写关于三阶的.只要把这个三阶行列式里每一个元素打进去就能算出值来了.过两天再写余子式的展开. 1 #in

【矩阵与行列式】矩阵和行列式学习笔记

开始从ToDoList里挑东西来杀. 感觉矩阵和行列式这两个跟很多东西都有关而且接触最少 所以先从它们开始补>w< P.S.看了很多资料,他们对矩阵和行列式这些东西的介绍都很丧病-我会尽量用通俗的语言来写我的笔记= =如果您不喜欢这种风格QAQ那我也没办法了请隔壁看别人的吧 ---------线割分是我>w<--------------– 什么是矩阵? 矩阵是n*m个数在n*m这个二维区域内的一个排列,是一个横纵排列的二维数字表格. 也就是说,矩阵只是一些数的一种存储形式. 通常我

矩阵与行列式的几何意义

作者:童哲链接:https://www.zhihu.com/question/36966326/answer/70687817来源:知乎著作权归作者所有,转载请联系作者获得授权. 行列式这个“怪物”定义初看很奇怪,一堆逆序数什么的让人不免觉得恐惧,但其实它是有实际得不能更实际的物理意义的,理解只需要三步.这酸爽~ 1,行列式是针对一个的矩阵而言的.表示一个维空间到维空间的线性变换.那么什么是线性变换呢?无非是一个压缩或拉伸啊.假想原来空间中有一个维的立方体(随便什么形状),其中立方体内的每一个点

矩阵的行列式的余子式计算

在n阶行列式中,把元素aij所在的第i行和第j列划去,留下来的n-1阶行列式叫做元素aij的余子式,记作Mij,令Aij=(-1)i+jMij,并称之为aij的代数余子式. 例如,四阶行列式 a11 a12 a13 a14 a21 a22 a23 a24 a31a32a33 a34 a41 a42 a43 a44 中a32的余子式为M32= a11 a13 a14 a21 a23 a24 a41 a43 a44 代数余子式A32=(-1)3+2M32= -M32 N阶行列式D等于它的任意一行(列

求行列式的值(递归)

/* #include <math.h> #include <stdio.h> #define N 100 #define LIM -100000000 float det(float a[N][N],int n){ if(n==1) return a[0][0]; if(n==2) return a[0][0]*a[1][1]-a[0][1]*a[1][0];// the base situation else{ int j,i,flag=1; float ret=0; for(

Armadillo之计算矩阵的行列式(determinant)

计算矩阵的行列式很简单,用det方法或是log_det方法 1 det(A) 如果A不是方阵的(square),将抛出std::logic_error异常 例: mat m = "3,2,4;1,-2,3;2,3,2;"; double d = det(m); cout << d << endl; 运行结果是-3 2 log_det(value, sign,A) 文档里推荐当矩阵A比较大时,使用本函数来代替det函数(估计会加快计算速度) det(A)=exp(

[转载]机器学习中常用的矩阵求导公式

原文地址:机器学习中常用的矩阵求导公式作者:MachineLearner 矩阵求导好像读书的时候都没学过,因为讲矩阵的课程上不讲求导,讲求导的课又不提矩阵.如果从事机器学习方面的工作,那就一定会遇到矩阵求导的东西.维基百科上:http://en.wikipedia.org/wiki/Matrix_calculus , 根据Y与X的不同类型(实值,向量,矩阵),给出了具体的求导公式,以及一堆相关的公式,查起来都费劲. 其实在实际的机器学习工作中,最常用到的就是实值函数y对向量X的求导,定义如下(其

矩阵求导

Y = A * X --> DY/DX = A'Y = X * A --> DY/DX = AY = A' * X * B --> DY/DX = A * B'Y = A' * X' * B --> DY/DX = B * A' 于是把以前学过的矩阵求导部分整理一下: 1. 矩阵Y对标量x求导: 相当于每个元素求导数后转置一下,注意M×N矩阵求导后变成N×M了 Y = [y(ij)] --> dY/dx = [dy(ji)/dx] 2. 标量y对列向量X求导: 注意与上面不同

利用矩阵求斐波那契数列

利用矩阵求斐波那契数列 flyfish 2015-8-27 矩阵(matrix)定义 一个m*n的矩阵是一个由m行n列元素排成的矩形阵列.矩阵里的元素可以是数字符号或者数学式. 形如 {acbd} 的数表称为二阶矩阵,它由二行二列组成,其中a,b,c,d称为这个矩阵的元素. 形如 {x1x2} 的有序对称为列向量Column vector 设 A={acbd} X={x1x2} 则 Y={ax1+bx2cx1+dx2} 称为二阶矩阵A与平面向量X的乘积,记为AX=Y 斐波那契(Fibonacci