第一次做矩阵树定理的题,其实就是记了个结论也没太看证明,然后学了学怎么用高斯消元求行列式,整数消元还真别扭,要用辗转相除,然后要注意取模的问题,一开始以为hzwer写麻烦了,后来想了想不加外面那句话会有问题,因为取模了。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#define mod 1000000000
using namespace std;
int dx[4]={1,-1,0,0};
int dy[4]={0,0,1,-1};
long long a[110][110];
int n,m,id;
int vis[110][110];
char s[110];
long long det(int n)
{
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
a[i][j]=(a[i][j]+mod)%mod;
long long ans=1,f=1;
for (int i=1;i<=n;i++)
{
for (int j=i+1;j<=n;j++)
{
long long A=a[i][i],B=a[j][i];
while (B)
{
long long t=A/B;A%=B;swap(A,B);
for (int k=i;k<=n;k++)
a[i][k]=(a[i][k]-t*a[j][k]%mod+mod)%mod;
for (int k=i;k<=n;k++) swap(a[i][k],a[j][k]);
f=-f;
}
}
if (!a[i][i]) return 0;
ans=ans*a[i][i]%mod;
}
if (f==-1) ans=(mod-ans)%mod;
return ans;
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
{
scanf("%s",s+1);
for (int j=1;j<=m;j++)
if (s[j]=='.') vis[i][j]=++id;
}
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
if (vis[i][j])
for (int k=0;k<4;k++)
{
int x=i+dx[k],y=j+dy[k];
if (x<=0 || y<=0 || x>n || y>m || !vis[x][y]) continue;
a[vis[i][j]][vis[i][j]]++;a[vis[i][j]][vis[x][y]]--;
}
printf("%lld\n",det(id-1));
return 0;
}