BZOJ 1002 轮状病毒
2015-12-17 13:58
316 查看
这是很久前看到的题了,一直不知如何下手,有一段时间误解了。直到前天决定对这道题下手了。去百度了一下,有人说是和基尔霍夫矩阵有关,也有人曾说和卢卡斯数列有关。
一开始看了基尔霍夫矩阵,真的是一脸茫然,这是怎么解决这道题的呢!后来仔细看了题目,的确这可以算是一道生成树的计数问题。(因为任意两点间都只有一条通路)。那么基尔霍夫矩阵便是解决这一问题的方法。
首先,基尔霍夫矩阵是有一个无向图的度矩阵对应地减去一个图的邻接矩阵得到的。如图,这是个无向图。 第二个图是它的度矩阵(度矩阵只有当 i == j 的时候 a[i][j]才有值,其他都为0 );
第三个图是邻接矩阵,第四个图便是基尔霍夫矩阵。
生成矩阵之后,要接着得到它的 n-1 阶主子式(即该n阶矩阵同时去掉第r行,第r列得到的,其中r为任意小于n大于0的一个整数);
最后要对其进行高斯消元得到他的三角形行列式(上三角矩阵)即主对角线下面的数都为0。最后将主对角线上的数都乘起来,便是最终结果。然而蒟蒻并不会证明。
通过基尔霍夫矩阵得出比较小的一些值后,就可以开始找规律了。最终得出的递推式是 F
= F[n-1]*3-F[n-2]+2;(从网上的许多题解中很多人都涉及到一点,如果遇到这种题,很有可能是要递推找规律的);
以下是基尔霍夫矩阵的代码。ca为输入数据组数,n为图的总点数,m为图的总边数。
以下是BZOJ 1002的代码
一开始看了基尔霍夫矩阵,真的是一脸茫然,这是怎么解决这道题的呢!后来仔细看了题目,的确这可以算是一道生成树的计数问题。(因为任意两点间都只有一条通路)。那么基尔霍夫矩阵便是解决这一问题的方法。
首先,基尔霍夫矩阵是有一个无向图的度矩阵对应地减去一个图的邻接矩阵得到的。如图,这是个无向图。 第二个图是它的度矩阵(度矩阵只有当 i == j 的时候 a[i][j]才有值,其他都为0 );
第三个图是邻接矩阵,第四个图便是基尔霍夫矩阵。
生成矩阵之后,要接着得到它的 n-1 阶主子式(即该n阶矩阵同时去掉第r行,第r列得到的,其中r为任意小于n大于0的一个整数);
最后要对其进行高斯消元得到他的三角形行列式(上三角矩阵)即主对角线下面的数都为0。最后将主对角线上的数都乘起来,便是最终结果。然而蒟蒻并不会证明。
通过基尔霍夫矩阵得出比较小的一些值后,就可以开始找规律了。最终得出的递推式是 F
= F[n-1]*3-F[n-2]+2;(从网上的许多题解中很多人都涉及到一点,如果遇到这种题,很有可能是要递推找规律的);
以下是基尔霍夫矩阵的代码。ca为输入数据组数,n为图的总点数,m为图的总边数。
#include<cstdio> #include<iostream> #include<cstring> #define rep(i,j,k) for(int i = j; i <= k; i++) #define maxn 25 #define LL long long using namespace std; LL c[maxn][maxn] = {0}, n, m; int read() { int s = 0, t = 1; char c = getchar(); while( !isdigit(c) ){ if( c == '-' ) t = -1; c = getchar(); } while( isdigit(c) ){ s = s * 10 + c - '0'; c = getchar(); } return s * t; } LL det() { LL ans = 1; rep(i,1,n-1){ rep(j,i+1,n-1){ while( c[j][i] ){ LL f = c[i][i] / c[j][i]; if( f ) { rep(l,i,n-1) c[i][l] -= f * c[j][l]; } rep(l,i,n-1) swap(c[i][l],c[j][l]); } } ans *= c[i][i]; if( !ans ) return 0; } return ans < 0? -ans : ans; } int main() { int ca = read(); while( ca-- ){ memset(c,0,sizeof(c)); n = read(), m = read(); rep(i,1,m){ int u = read(), v = read(); u--, v--; c[u][u]++, c[v][v]++; c[u][v]--, c[v][u]--; } cout<<det(); } return 0; }
以下是BZOJ 1002的代码
#include<cstdio> #include<iostream> #include<cstring> #define rep(i,j,k) for(int i = j; i <= k; i++) #define down(i,j,k) for(int i = j; i >= k; i--) #define maxn 110 using namespace std; int mol = 10000; int read() { int s = 0, t = 1; char c = getchar(); while( !isdigit(c) ){ if( c == '-' ) t = -1; c =getchar(); } while( isdigit(c) ){ s = s * 10+ c - '0'; c = getchar(); } return s * t; } struct data{ int a[40]; data(){ memset(a,0,sizeof(a)); } }; data datas[maxn]; data mul(data a,int b) { rep(i,1,a.a[0]){ a.a[i] *= b; } rep(i,1,a.a[0]+2){ a.a[i+1] += a.a[i] / mol; a.a[i] %= mol; } while( a.a[a.a[0]+1] ){ a.a[0]++; } return a; } data sub(data a,data b) { a.a[1] += 2; down(i,a.a[0],1){ if( a.a[i] < b.a[i] ){ a.a[i+1]--, a.a[i] += mol; } a.a[i] -= b.a[i]; } while( !a.a[a.a[0]] ) { a.a[0]--; } return a; } int main() { int n = read(); datas[1].a[0] = datas[2].a[0] = 1; datas[1].a[1] = 1, datas[2].a[1] = 5; rep(i,3,n){ datas[i] = sub(mul(datas[i-1],3),datas[i-2]); } int s = datas .a[0]; printf("%d", datas .a[s]); down(i,s-1,1){ printf("%04d", datas .a[i] ); } cout<<endl; return 0; }
相关文章推荐
- 【转】使用Sublime + PlantUML高效地画图
- hdu-1056 HangOver
- Mac 下配置php环境
- linux指令--ls
- Jmeter之使用CSV Data Set Config实现参数化登录
- linux指令--ls
- python内置函数大全
- 借助常见工具快捷实现录音文件的查找与导出
- NODE.JS入门示例
- hdu-1048 The Hardest Problem Ever
- 去掉windows文件末尾的^M: %s/\r//g
- 最小生成树,克鲁斯卡尔算法(Python实现)
- 菜鸟猿大战Java之集合框架系列(一)
- 去掉windows文件末尾的^M: %s/\r//g
- hdu-1040 As Easy As A+B
- centos7安装配置open***
- 测试庖丁解牛分词工具
- [LeetCode]Find Median from Data Stream
- OpenCV2:Mat属性type,depth,step
- 公约数数列