标签:return fine blog 一个 tin 两种 ace log while
题目描述
输入
输出
第一行一个整数,问题所求的方案数。
样例输入
8
01111111
00101001
01010111
01001111
01110101
01110011
01111100
01110110
样例输出
72373
题解
矩阵树定理
读明白题以后发现求的就是外向树形图的个数,于是使用矩阵树定理解决。
与求生成树个数不同的是,外向树形图用的矩阵是 入度矩阵-邻接矩阵 ,并且删去的一行一列不能随便选择,必须是根所在的那一行那一列。
然后高斯消元求一下行列式的值即可。
#include <cstdio> #include <cstring> #include <algorithm> #define N 310 #define mod 1000000007 using namespace std; typedef long long ll; ll a[N][N]; char str[N]; inline ll pow(ll x , ll y) { ll ans = 1; while(y) { if(y & 1) ans = ans * x % mod; x = x * x % mod , y >>= 1; } return ans; } int main() { int n , i , j , k , d = 0; ll t , ans = 1; scanf("%d" , &n); for(i = 0 ; i < n ; i ++ ) { scanf("%s" , str); for(j = 0 ; j < n ; j ++ ) if(str[j] == ‘1‘) a[j][j] ++ , a[i][j] -- ; } for(i = 1 ; i < n ; i ++ ) { for(j = i ; j < n ; j ++ ) if(a[j][i]) break; if(j >= n) continue; if(j != i) for(d ^= 1 , k = i ; k < n ; k ++ ) swap(a[i][k] , a[j][k]); ans = ans * a[i][i] % mod; for(t = pow(a[i][i] , mod - 2) , j = i ; j < n ; j ++ ) a[i][j] = a[i][j] * t % mod; for(j = i + 1 ; j < n ; j ++ ) for(t = a[j][i] , k = i ; k < n ; k ++ ) a[j][k] = (a[j][k] - a[i][k] * t % mod + mod) % mod; } for(i = 1 ; i < n ; i ++ ) ans = ans * a[i][i] % mod; if(d) ans = (mod - ans) % mod; printf("%lld\n" , ans); return 0; }
标签:return fine blog 一个 tin 两种 ace log while
原文地址:http://www.cnblogs.com/GXZlegend/p/7493203.html