讲题
#include <stdio.h> #define maxn 1005 #define mod 1000000007 int cas,t = 1,road[maxn][maxn],n,k,ra,rb; long long A[maxn],dp[maxn][maxn],size[maxn],ans; /*dp[i][j]表示从1到i节点有j个节点是其字数的最大值*/ void init() { int i,j; A[0] = 1; for(i = 1;i < maxn;i ++) { A[i] = A[i-1] * i % mod; } } void init1() { int i,j; for(i = 1;i <= n;i ++) { size[i] = 1; for(j = 1;j <= n;j ++) dp[i][j] = road[i][j] = 0; } } long long fast_pow(long long x, int n) { long long ret = 1; while (n) { if (n&1) ret = ret * x % mod; n >>= 1; x = x * x % mod; } return ret; } long long inv(long long x) { return fast_pow(x, mod-2); } /*得到以每个点为根的子树的节点数*/ void LookRoad(int r) { int i; for(i = 1;i <= n;i ++) { if(road[r][i]) { road[r][i] = road[i][r] = 0; LookRoad(i); size[r] += size[i]; } } } int main() { int i,j; long long p,q; scanf("%d",&cas); init(); while(cas --) { scanf("%d %d",&n,&k); init1(); for(i = 1;i < n;i ++) { scanf("%d %d",&ra,&rb); road[ra][rb] = road[rb][ra] = 1; } LookRoad(1); /*逆元代替分数*/ dp[0][0] = 1; dp[0][1] = 0; for(i = 1;i <= n;i ++) { p = inv(size[i]); /*该点是最大点的概率*/ q = (size[i]-1)*p%mod; /*该点不是最大点的概率*/ dp[i][0] = dp[i-1][0] * q % mod; for(j = 1;j <= i;j ++) { dp[i][j] = (dp[i-1][j-1]*p%mod + dp[i-1][j]*q%mod)%mod; } } ans = dp[n][k] * A[n] % mod; printf("Case #%d: %lld\n",t++,ans); } return 0; }
posted on 2016-03-24 13:33 Tob's_the_top 阅读(110) 评论(0) 编辑 收藏 举报