P4111 [HEOI2015]小Z的房间

题目

P4111 [HEOI2015]小Z的房间

做法

思路很容易想,但是坑点多啊!!

首先有墙,并不能所有点都堆到矩阵然后去末行求\(det\),非墙点才能丢进矩阵

动态开一下点

有模数,不是素数,也用不了逆元,我们就要用求\(det\)的黑科技,辗转相除法

具体看代码

My complete code

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<ctime>
using namespace std;
typedef long long LL;
const LL maxn=100;
const LL p=1e9;
const LL dx[2]={-1,0},dy[2]={0,-1};
LL n,m,tot;
LL D[maxn][maxn],mp[maxn][maxn],id[maxn][maxn];
bool visit[maxn];
inline LL Solve(){
    LL N=tot-1,tr(0),ans(1);
    for(LL i=1;i<=N;++i){
        if(visit[i])
            continue;
        for(LL j=i+1;j<=N;++j){
            if(visit[j])
                continue;
            while(D[j][i]){
                LL tmp=D[i][i]/D[j][i];
                for(LL k=1;k<=N;++k){
                    D[i][k]=(D[i][k]-tmp*D[j][k]%p+p)%p;
                    swap(D[j][k],D[i][k]);
                }
                tr^=1;
            }
        }
        if(D[i][i]==0)
            return 0;
        ans=ans*D[i][i]%p;
    }
    if(tr)
        ans=(p-ans+p)%p;
    return ans;
}
int main(){
    scanf("%lld%lld",&n,&m);
    for(LL i=1;i<=n;++i){
        char s[maxn];
        scanf(" %s",s+1);
        for(LL j=1;j<=m;++j)
            if(s[j]=='.')
                mp[i][j]=1;
    }
    for(LL i=1;i<=n;++i){
        for(LL j=1;j<=m;++j){
            if(mp[i][j]==0)
                continue;
            id[i][j]=++tot;
            LL u(id[i][j]);
            for(LL k=0;k<2;++k){
                LL xx(i+dx[k]),yy(j+dy[k]);
                if(mp[xx][yy]==0)
                    continue;
                LL v(id[xx][yy]);
                ++D[u][u],
                ++D[v][v],
                D[u][v]=(D[u][v]+p-1)%p,
                D[v][u]=(D[v][u]+p-1)%p;
            }
        }
    }
    printf("%lld\n",Solve());
    return 0;
}
posted @ 2019-01-14 10:14  y2823774827y  阅读(388)  评论(0编辑  收藏  举报