题目:
题解:
利用类似辗转相除的方法,避免了对1e9取余,就可以避开做除法的过程。
因为每次交换行,都会使行列式的值变成原来的-1倍,因为是取模,所以不能对最后的结果直接取绝对值。需要记录交换的次数,然后计算答案,再进行取模。
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
using namespace std;
const int mod=1e9;
char st[105][105];
int c[2][2]={{1,0},{0,1}};
int a[100][100],sb[105][105];
LL gauss(int n)
{
bool flag=0;
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++) a[i][j]%=mod;
LL ans=1;
for (int i=1;i<=n;i++)
{
int num=i;
for (int j=i;j<=n;j++)
if (abs(a[i][i])<abs(a[j][i])) num=j;
if (!a[num][i]) return 0;
if (num!=i)
{
for (int j=i;j<=n;j++) swap(a[num][j],a[i][j]);
flag^=1;
}
for (int j=i+1;j<=n;j++)
while (a[j][i])
{
LL t=a[j][i]/a[i][i];
for (int k=i;k<=n;k++) a[j][k]=(a[j][k]-t*a[i][k])%mod;
if (!a[j][i]) break;flag^=1;
for (int k=i;k<=n;k++) swap(a[j][k],a[i][k]);
}
ans=ans*a[i][i]%mod;
}
if (flag) ans=-ans;
return (ans+mod)%mod;
}
int main()
{
int n,m,now=0;scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
{
scanf("%s",st[i]);
for (int j=1;j<=m;j++)
if (st[i][j-1]=='.') sb[i][j]=++now;
}
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
if (st[i][j-1]=='.')
for (int k=0;k<2;k++)
{
int x=i+c[k][0],y=j+c[k][1];
if (x<=0 || y<=0 || x>n || y>m || st[x][y-1]=='*') continue;
int nc=sb[i][j],oth=sb[x][y];
a[nc][nc]++; a[oth][oth]++;
a[oth][nc]--; a[nc][oth]--;
}
printf("%lld",gauss(now-1));
}