bzoj4031(洛谷P4111) [HEOI2015]小Z的房间(矩阵树定理)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sunshiness_s/article/details/81406946

题解

连一些边,然后矩阵树定理就可以了

但是注意这里的模数不是质数!
因此不能用逆元啥的,需要辗转相除!!!


代码

#include <cstdio>
#include <algorithm>
using namespace std;
#define ll long long
#define N 90
#define mod 1000000000
char str[N];
int n,m,num,a[N][N],id[10][10]; 
inline void insert(int x,int y){
    a[x][x]++;a[y][y]++;
    a[x][y]--;a[y][x]--;
}
inline void gauss(){
    ll ans=1;--num;
    for(int i=1;i<=num;i++){
        int r=i;
        while(r<=num&& !a[r][i]) r++;
        if(r>num){puts("0");return ;}
        if(r!=i){
            ans*=-1;
            for(int j=i;j<=num;j++) swap(a[r][j],a[i][j]);
        }
        for(int j=i+1;j<=num;j++){
            while(a[j][i]){
                ll t=a[j][i]/a[i][i];
                for(int k=i;k<=num;k++) a[j][k]=(a[j][k]-(ll)t*a[i][k]%mod+mod)%mod;
                if(!a[j][i]) break;
                ans*=-1;
                for(int k=i;k<=num;k++) swap(a[j][k],a[i][k]); 
            }
        }
    }
    for(int i=1;i<=num;i++) ans=ans*a[i][i]%mod;
    printf("%lld\n",(ans+mod)%mod);
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%s",str+1);
        for(int j=1;j<=m;j++){
            if(str[j]=='.'){
                id[i][j]=++num;
                if(id[i-1][j]) insert(id[i-1][j],id[i][j]);
                if(id[i][j-1]) insert(id[i][j-1],id[i][j]); 
            } 
        }
    }
    gauss();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sunshiness_s/article/details/81406946
今日推荐