BZOJ4031;[HEOI2015]小Z的房间
矩阵树定理模板题。
因为膜的不是pps质数,所以要用辗转相除法来消元。
#include <cstdio>
#include <algorithm>
using namespace std;
const int pps=1e9;
int n,m,id;
char s[10];
int dx[4]={0,1,0,-1};
int dy[4]={1,0,-1,0};
int p[10][10],a[82][82];
int read() {
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
}
int Gauss(int n) {
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
a[i][j]=(a[i][j]%pps+pps)%pps;
int ans=1,s=0;
for(int i=1;i<=n;i++) {
int r=i;
for(;r<=n;r++)if(a[r][i])break;
if(r==n+1)return 0;
if(r!=i) {
for(int j=i;j<=n;j++)swap(a[i][j],a[r][j]);
s^=1;
}
for(r=i+1;r<=n;r++) {
while(a[r][i]) {
int tmp=a[r][i]/a[i][i];
for(int j=i;j<=n;j++)
a[r][j]=((a[r][j]-1ll*tmp*a[i][j])%pps+pps)%pps;
if(!a[r][i])break;
s^=1;
for(int j=i;j<=n;j++)swap(a[i][j],a[r][j]);
}
}
ans=1ll*ans*a[i][i]%pps;
}
if(s)ans=(pps-ans)%pps;
return ans;
}
int main() {
n=read(),m=read();
for(int i=1;i<=n;i++) {
scanf("%s",s+1);
for(int j=1;j<=m;j++)
if(s[j]=='.')p[i][j]=++id;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
for(int k=0;k<4;k++) {
int x=i+dx[k],y=j+dy[k];
if(!p[x][y]||x<1||x>n||y<1||y>m)continue;
int u=p[i][j],v=p[x][y];
a[u][u]++;a[u][v]--;
}
printf("%d\n",Gauss(id-1));
return 0;
}