#include <iostream> #define maxn 1005 #define mod 1000000007 using namespace std; int cas,t = 1,road[maxn][maxn],n,k,ra,rb; long long A[maxn],dp[maxn][maxn],size[maxn]; /*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() { cin >> cas; init(); while(cas --) { cin >> n >> k; init1(); for(int i = 1;i < n;i ++) { cin >> ra >> rb; road[ra][rb] = road[rb][ra] = 1; } LookRoad(1); /*逆元代替分数*/ dp[0][0] = 1; dp[0][1] = 0; for(int i = 1;i <= n;i ++) { long long p,q; p = inv(size[i]); /*该点是最大点的概率*/ q = (size[i]-1)*p%mod; /*该点不是最大点的概率*/ //cout << p << endl; // cout << q << endl; dp[i][0] = dp[i-1][0] * q % mod; for(int j = 1;j <= i;j ++) { dp[i][j] = (dp[i-1][j-1]*p%mod + dp[i-1][j]*q%mod)%mod; } } long long ans; ans = dp[n][k] * A[n] % mod; cout << "Case #" << t ++ << ": " << ans << endl; } return 0; }
小结:逆元替代分数的这种做法还没有理解。