bzoj2467 [中山市选2010]生成树
Description
有一种图形叫做五角形圈。一个五角形圈的中心有1个由n个顶点和n条边组成的圈。在中心的这个n边圈的每一条边同时也是某一个五角形的一条边,一共有n个不同的五角形。这些五角形只在五角形圈的中心的圈上有公共的顶点。如图0所示是一个4-五角形圈。
现在给定一个n五角形圈,你的任务就是求出n五角形圈的不同生成树的数目。还记得什么是图的生成树吗?一个图的生成树是保留原图的所有顶点以及顶点的数目减去一这么多条边,从而生成的一棵树。
注意:在给定的n五角形圈中所有顶点均视为不同的顶点。
Input
输入包含多组测试数据。第一行包含一个正整数T,表示测试数据数目。每组测试数据包含一个整数n( 2<=N<=100),代表你需要求解的五角形圈中心的边数。
Output
对每一组测试数据,输出一行包含一个整数x,表示n五角形圈的生成树数目模2007之后的结果。
Sample Input
1
2
2
Sample Output
40
正解:矩阵树定理或组合数学。
首先用矩阵树定理打表,发现$Ans=4*n*5^{n-1}$,于是愉快$AC$
下面给出严谨证明:(来自ljh2000神犇:http://www.cnblogs.com/ljh2000-jump/p/6522954.html)
考虑如果$n$个五边形每个断掉一条边就会得到一个基环外向树,此时还需要断掉一条边,这意味着$n$个五边形中就有一个五边形要断掉两条边,并且容易想到有一条必然是在中心的那个$n$边形上,那么就可以用组合数学来表示了。从$n$个五边形中选取一个是选两条边的,这个五边形在中央$n$边形上那条边必选,那么只需在剩下$4$条边再断一条即可,而剩下的$n-1$个五边形都是随便断一条即可,总方案数就是$4*n*5^{n-1}$。
1 //It is made by wfj_2048~ 2 #include <algorithm> 3 #include <iostream> 4 #include <complex> 5 #include <cstring> 6 #include <cstdlib> 7 #include <cstdio> 8 #include <vector> 9 #include <cmath> 10 #include <queue> 11 #include <stack> 12 #include <map> 13 #include <set> 14 #define inf (1<<30) 15 #define rhl (2007) 16 #define eps (1e-9) 17 #define il inline 18 #define RG register 19 #define ll long long 20 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) 21 22 using namespace std; 23 24 int d[410][410],g[410][410],bin[110],n,N; 25 double a[410][410],ans; 26 27 il int gi(){ 28 RG int x=0,q=1; RG char ch=getchar(); 29 while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); 30 if (ch=='-') q=-1,ch=getchar(); 31 while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); 32 return q*x; 33 } 34 35 il void insert(RG int x,RG int y){ g[x][y]++,d[x][x]++; return; } 36 37 il void gauss(){ 38 ans=1; 39 for (RG int i=1;i<N;++i){ 40 RG int id=i; RG double t=a[i][i]; 41 for (RG int j=i+1;j<N;++j) 42 if (t<fabs(a[j][i])+eps) t=fabs(a[j][i]),id=j; 43 for (RG int j=1;j<N;++j) swap(a[i][j],a[id][j]); 44 for (RG int j=i+1;j<N;++j){ 45 t=a[j][i]/a[i][i]; 46 for (RG int k=i;k<N;++k) a[j][k]-=t*a[i][k]; 47 } 48 if (fabs(a[i][i])<eps){ ans=0; return; } ans*=a[i][i]; 49 } 50 if (ans<0) ans=-ans; return; 51 } 52 53 /* 54 il void work(){ 55 memset(g,0,sizeof(g)),memset(d,0,sizeof(d)); 56 n=gi(),insert(1,n),insert(n,1); N=n; 57 for (RG int i=1;i<n;++i) insert(i,i+1),insert(i+1,i); 58 for (RG int i=1;i<=n;++i){ 59 N++,insert(i,N),insert(N,i); 60 N++,insert(N-1,N),insert(N,N-1); 61 N++,insert(N-1,N),insert(N,N-1); 62 if (i<n) insert(N,i+1),insert(i+1,N); 63 else insert(N,1),insert(1,N); 64 } 65 for (RG int i=1;i<=N;++i) 66 for (RG int j=1;j<=N;++j) a[i][j]=d[i][j]-g[i][j]; 67 gauss(); printf("%d\n",(int)ans); return; 68 } 69 */ 70 71 int main(){ 72 File("tree"); 73 RG int T=gi(); bin[0]=1; 74 for (RG int i=1;i<=100;++i) bin[i]=bin[i-1]*5%rhl; 75 while (T--) n=gi(),printf("%d\n",4*n*bin[n-1]%rhl); 76 return 0; 77 }