大一上学了线代,脑子里面还没有对线代的具体应用有过认识,听说以后机器学习什么的会用上,但好像学到的时候线代知识也容易忘了……
那么今天就说说在oi里面,我用到线代的知识的题目吧。
矩阵快速幂。
这类题目主要是用来推导公式的,比如经典的斐波那契数列就可以用上这个。
F【n】=F【n-1】+F【n-2】
那么我们求的时候就之间算单位矩阵的n次方就行了,
怎么求呢?其实就是把快速幂里面的整数换成矩阵相乘。代码就不贴了。
矩阵树定理
https://www.cnblogs.com/twilight-sx/p/9064208.html这篇博客有题目也有讲解,十分详细。
矩阵树定理用于求解一个图上的生成树个数。实现方法就是博客里面所说的,求出那个K矩阵后,之间高斯消元,算出行列式,然后就得出答案。
原理是什么我不懂,记住就好。
贴上洛谷模板题P4111 [HEOI2015]小 Z 的房间
#include <bits/stdc++.h> #define maxn 90 #define mod 1000000000 typedef long long ll; using namespace std; const int dx[3]={0,1,0}; const int dy[3]={0,0,1}; ll n, m, f[maxn][maxn]; ll cnt, b[maxn][maxn]; int i,j,k; char c; ll Gauss() { ll ans = 1; for(int i = 1; i < cnt; i ++) { for(int j = i + 1; j < cnt; j ++) while(f[j][i]) { ll t = f[i][i] / f[j][i]; for(int k = i; k < cnt; k ++) f[i][k] = (f[i][k] - t * f[j][k] + mod) % mod; swap(f[i], f[j]); ans = - ans; } ans = (ans * f[i][i]) % mod; } return (ans + mod) % mod; } int main() { scanf("%d%d",&n,&m); //getchar(); for (i=1;i<=n;i++) { //getchar(); for (j=1;j<=m;j++) { // getchar(); cin>>c; //cout<<a[i][j]; if (c=='.') b[i][j]=++cnt; } } //cnt--; for (i=1;i<=n;i++) for (j=1;j<=m;j++) { if (b[i][j]) for (k=1;k<=2;k++) { int xx=i+dx[k]; int yy=j+dy[k]; if (b[xx][yy] && xx>=1 && xx<=n && yy>=1 && yy<=m) { f[b[xx][yy]][b[xx][yy]]++; f[b[i][j]][b[i][j]]++; f[b[xx][yy]][b[i][j]]--; f[b[i][j]][b[xx][yy]]--; } } } printf("%lld ",Gauss()); return 0; }
对了,高斯消元那里最好按照那篇博客里面的那种写法,我想模拟现实中的算法,发现不行,也不知道哪里错。