题意:
数据范围:n,m<=9
解法:
矩阵树定理模板题
这题答案需要模1e9,而高斯消元的过程中有除法,
因此本题需要用辗转相除法(欧几里得算法),复杂度多一个log
code:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxm=15;
const int mod=1e9;
char s[maxm][maxm];
int id[maxm][maxm],idx;
int n,m;
int K[105][105];
int ppow(int a,int b,int mod){
int ans=1%mod;a%=mod;
while(b){
if(b&1)ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
int guass(int n){
int ans=1;
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
while(K[j][i]){//直到为0
int t=K[i][i]/K[j][i];//计算第i行对应的数是第j行的几倍
for(int k=i;k<=n;k++){//一个一个消去并交换数字(消去之后之前的位置变小)
K[i][k]=(K[i][k]-t*K[j][k]%mod+mod)%mod;
swap(K[i][k],K[j][k]);//交换
}
ans=-ans;//交换行,行列式的值取反
}
}
if(!K[i][i])return 0;//生成树数量为0
ans=(ans*K[i][i]%mod+mod)%mod;//上三角行列式(右上角)的值为对角线乘积
}
return ans;
}
void add(int a,int b){
K[a][a]++;
K[b][b]++;
K[a][b]--;
K[b][a]--;
}
signed main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
scanf("%s",s[i]+1);
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(s[i][j]=='.'){
id[i][j]=++idx;
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(id[i][j]&&id[i][j+1]){
add(id[i][j],id[i][j+1]);
}
if(id[i][j]&&id[i+1][j]){
add(id[i][j],id[i+1][j]);
}
}
}
int ans=guass(idx-1);
cout<<ans<<endl;
return 0;
}