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;
}

posted on 2018-08-18 14:49  HYSBZ_mzf  阅读(109)  评论(0编辑  收藏  举报

导航