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