1. 程式人生 > >BZOJ4031: [HEOI2015]小Z的房間

BZOJ4031: [HEOI2015]小Z的房間

直接 col div ans tdi printf scan clas img

n,m<=9,n*m的網格圖,相鄰的.可連邊,問把所有的.連成一棵樹有多少方案,%1e9。

直接矩陣樹,然而高斯消元時模數不是質數沒法直接除,所以利用行列式的性質,某一行乘某個數加到另一行上,這樣輾轉相除。

技術分享圖片
 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 #include<stdlib.h>
 5 //#include<queue>
 6 #include<math.h>
 7 //#include<time.h>
 8
//#include<iostream> 9 using namespace std; 10 11 int n,m,tot=0; 12 char mp[13][13]; 13 int mat[111][111],who[111][111]; 14 const int mod=1e9; 15 16 int gauss(int n) 17 { 18 for (int i=1;i<=n;i++) 19 for (int j=1;j<=n;j++) 20 mat[i][j]+=mat[i][j]<0?mod:0; 21 int
ans=1; 22 for (int i=1;i<=n;i++) 23 for (int j=i+1;j<=n;j++) 24 { 25 int A=mat[i][i],B=mat[j][i]; 26 while (B) 27 { 28 int t=A/B; A%=B; swap(A,B); 29 for (int k=i;k<=n;k++) 30 mat[i][k]-=1ll*mat[j][k]*t%mod,
31 mat[i][k]+=mat[i][k]<0?mod:0; 32 for (int k=i;k<=n;k++) {int t=mat[j][k]; mat[j][k]=mat[i][k]; mat[i][k]=t;} 33 ans=ans==1?mod-1:1; 34 } 35 } 36 for (int i=1;i<=n;i++) ans=1ll*ans*mat[i][i]%mod; 37 return ans; 38 } 39 40 int main() 41 { 42 scanf("%d%d",&n,&m); 43 for (int i=1;i<=n;i++) scanf("%s",mp[i]+1); 44 for (int i=1;i<=n;i++) 45 for (int j=1;j<=m;j++) 46 if (mp[i][j]==.) who[i][j]=++tot; 47 for (int i=1;i<=n;i++) 48 for (int j=1;j<=m;j++) 49 if (mp[i][j]==.) 50 { 51 if (mp[i+1][j]==.) mat[who[i][j]][who[i+1][j]]--,mat[who[i][j]][who[i][j]]++; 52 if (mp[i][j+1]==.) mat[who[i][j]][who[i][j+1]]--,mat[who[i][j]][who[i][j]]++; 53 if (mp[i-1][j]==.) mat[who[i][j]][who[i-1][j]]--,mat[who[i][j]][who[i][j]]++; 54 if (mp[i][j-1]==.) mat[who[i][j]][who[i][j-1]]--,mat[who[i][j]][who[i][j]]++; 55 } 56 printf("%d\n",gauss(tot-1)); 57 return 0; 58 }
View Code

BZOJ4031: [HEOI2015]小Z的房間