bzoj4031 小z的房间
题目大意:给定n*m的网格,有一些障碍点,求生成树的个数。
思路:矩阵数定理直接求解就可以了。但是因为要取模所以要稍微修改一下高斯消元,行列式交换行或列的时候行列式的值要变号。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define p 1000000000 #define LL long long #define maxm 105 using namespace std; char map[maxm][maxm]; int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1},bi[maxm][maxm]={0}; LL ai[maxm][maxm]={0}; char in(){ char ch; while(scanf("%c",&ch)==1){ if (ch==‘.‘||ch==‘*‘) return ch; } } int work(int n){ int i,j;LL x,y,k,ans=1,f=1,t; for (i=1;i<=n;++i) for (j=1;j<=n;++j) ai[i][j]=(ai[i][j]+p)%p; for (i=1;i<=n;++i){ for (j=i+1;j<=n;++j){ x=ai[i][i];y=ai[j][i]; while(y!=0){ k=x/y;x%=y;swap(x,y);f=-f; for (t=i;t<=n;++t) ai[i][t]=(ai[i][t]-k*ai[j][t]%p+p)%p; for (t=i;t<=n;++t) swap(ai[i][t],ai[j][t]); } }if (!ai[i][i]) return 0; ans=ans*ai[i][i]%p; }return (int)(ans*f%p+p)%p; } int main(){ int n,m,i,j,k,x,y,tot=0,u,v;scanf("%d%d",&n,&m); for (i=1;i<=n;++i){ for (j=1;j<=m;++j){map[i][j]=in();if (map[i][j]==‘.‘) bi[i][j]=++tot;} }for (i=1;i<=n;++i) for (j=1;j<=m;++j){ if (map[i][j]!=‘.‘) continue; for (k=0;k<4;++k){ x=i+dx[k];y=j+dy[k]; if (x<1||x>n||y<1||y>m||map[x][y]!=‘.‘) continue; u=bi[i][j];v=bi[x][y]; ++ai[u][u];--ai[u][v]; } }printf("%d\n",work(tot-1)); }
时间: 2024-12-17 10:46:41