关闭

HDU 5378 (概率dp)

117人阅读 评论(0) 收藏 举报
分类:

Leader in Tree Land

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


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 kministers 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 #xansx 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
 


题意:1-n随机分配给每一个节点,子树的值表示为子树中的节点的最大值.问

所有的子树值有k种的方案数.

每一个节点为根的子树中自身为最大值的概率是1/size(i).然后用f[i][j]表示为

前i个节点中有j种最大值的概率,转移方程就很简单了.因为要避免浮点数,概率

用逆元来搞.

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <map>
#include <vector>
using namespace std;
#define maxn 1111
#define maxm maxn*2
#define mod 1000000007

struct node {
    int v, next;
}edge[maxn];
int head[maxn], n, k, cnt;
long long dp[maxn];
long long rev[maxn];
long long f[maxn][maxn];

void add_edge (int u, int v) {
    edge[cnt].v = v, edge[cnt].next = head[u], head[u] = cnt++;
}

void dfs (int u, int fa) {
    dp[u] = 1;
    for (int i = head[u]; i != -1; i = edge[i].next) {
        int v = edge[i].v;
        if (v == fa)
            continue;
        dfs (v, u);
        dp[u] += dp[v];
    }
}

long long cal (long long num) {
    return (num%mod+mod)%mod;
}

long long solve () {
    for (int i = 1; i <= n; i++) dp[i] = rev[dp[i]]%mod;
    memset (f, 0, sizeof f);
    f[1][1] = dp[1];
    f[1][0] = cal (1-dp[1]);
    for (int i = 2; i <= n; i++) {
        for (int j = 0; j <= k; j++) {
            f[i][j] += f[i-1][j]*cal (1-dp[i])%mod;
            if (j)
                f[i][j] += f[i-1][j-1]*dp[i]%mod;
            f[i][j] %= mod;
        }
    }
    long long ans = 1;
    for (int i = 2; i <= n; i++)
        ans *= i, ans %= mod;
    return (ans*f[n][k] % mod);
}

void init() {  //预处理逆元
    rev[1] = 1;
    for (int i = 2; i <= 1000; i++){
        rev[i] = (long long)(mod - mod/i) * rev[mod % i] % mod;
    }
}

int main () {
    //freopen ("in.txt", "r", stdin);
    init ();
    int t, kase = 0;
    cin >> t;
    while (t--) {
        cin >> n >> k;
        memset (head, -1, sizeof head);
        cnt = 0;
        printf ("Case #%d: ", ++kase);
        for (int i = 1; i < n; i++) {
            int u, v;
            scanf ("%d%d", &u, &v);
            add_edge (u, v);
            add_edge (v, u);
        }
        dfs (1, 0);
        printf ("%lld\n", solve ());
    }
    return 0;
}


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:93556次
    • 积分:5370
    • 等级:
    • 排名:第5036名
    • 原创:463篇
    • 转载:0篇
    • 译文:0篇
    • 评论:12条
    最新评论