HDU 5378 Leader in Tree Land

可以用求概率的思想来解决这个问题。令以i号节点为根的子树为第i棵子树,设这颗子树恰好有sz[i]个点。那么第i个点是第i棵子树最大值的概率为1/sz[i],不是最大值的概率为(sz[i]-1)/sz[i]。现在可以求解恰好有k个最大值的概率。

令dp[i][j]表示考虑编号从1到i的点,其中恰好有j个点是其子树最大值的概率。 很容易得到如下转移方程:dp[i][j]=dp[i-1][j]*(sz[i]-1)/sz[i]+dp[i-1][j-1]/sz[i]。这样dp[n][k]就是所有点中恰好有k个最大值的概率。

题目要求的是方案数,用总数n!乘上概率就是答案。计算的时候用逆元代替上面的分数即可。

Leader in Tree Land

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 68    Accepted Submission(s): 26


Problem Description
Tree land has  n  cities, connected by  n1  roads. You can go to any city from any city. In other words, this land is a tree. The city numbered one is the root of this tree.

There are  n  ministers numbered from  1  to  n . You will send them to  n  cities, one city with one minister. 

Since this is a rooted tree, each city is a root of a subtree and there are  n  subtrees. The leader of a subtree is the minister with maximal number in this subtree. As you can see, one minister can be the leader of several subtrees. 

One day all the leaders attend a meet, you find that there are exactly  k  ministers. You want to know how many ways to send  n  ministers to each city so that there are  k ministers attend the meet.

Give your answer mod  1000000007 .
 

Input
Multiple test cases. In the first line there is an integer  T , indicating the number of test cases. For each test case, first line contains two numbers  n,k . Next  n1  line describe the roads of tree land.

T=10,1n1000,1kn
 

Output
For each test case, output one line. The output format is Case # x ans x  is the case number,starting from  1 .
 

Sample Input
   
   
   
   
2 3 2 1 2 1 3 10 8 2 1 3 2 4 1 5 3 6 1 7 3 8 7 9 7 10 6
 

Sample Output
   
   
   
   
Case #1: 4 Case #2: 316512
 

Source
2015 Multi-University Training Contest 7
 

#include <bits/stdc++.h>
using namespace std;
#define prt(k) cerr<<#k" = "<<k<<endl
typedef long long ll;
const ll inf = 0x3f3f3f3f;
const ll mod = 1e9+7;
const ll N = 1005;
int sz[N];
vector<int> g[N];
ll dp[N][N];
int  n, K;
ll fac[N];
ll pmod(ll a, ll n)
{
    ll r  = 1;
    for (; n>0; n>>=1, a=a*a%mod) {
        if (n & 1) r = r * a % mod;
    }
    return r;
}
inline ll inv(ll a)
{
    return pmod(a, mod - 2);
}
void dfs(int u, int fa)
{
    sz[u] = 1;
    for (int v: g[u]) if (v-fa) {
        dfs(v, u);
        sz[u] += sz[v];
    }
}
ll in[N];
int main()
{
    fac[0] = 1; in[1] = 1;
    for (ll i=1;i<N;i++) fac[i]=fac[i-1]*i%mod, in[i]=inv(i);
    int re; scanf("%d", &re); int ca= 1;
    while (re--) {
        memset(sz,0 , sizeof sz);
        scanf("%d%d", &n ,&K);
        for(ll i=0;i<=n;i++) g[i].clear();
        memset(dp, 0, sizeof dp);
        for (ll i=0;i<n-1;i++) {
            int u, v;
            scanf("%d%d", &u, &v);
            g[u].push_back(v);
            g[v].push_back(u);
        }
        dfs(1, 1);
        dp[0][0] = 1;
        for (int i=1;i<=n;i++)
        for (int j=0;j<=K;j++) {
            dp[i][j] = dp[i-1][j] * (sz[i] - 1) %mod
            * in[sz[i]] % mod;
            if (j > 0)
                dp[i][j] += dp[i-1][j-1] * in[sz[i]] % mod;
            dp[i][j] %= mod;
        }
        ll ans = dp[n][K] * fac[n] % mod;
        printf("Case #%d: %I64d\n", ca++, ans);
    }
    return 0;
}




你可能感兴趣的:(概率)