hdu 5378 Leader in Tree Land(dp+逆元)

来源:互联网 发布:泰国旅游 知乎 编辑:程序博客网 时间:2024/05/16 18:07

题目链接:hdu 5378 Leader in Tree Land


问题可以理解成N个节点的树,有K个ministers的概率,最后乘上N!。每个节点为ministers的概率即为1 / son(以该节点为根节点的子树包含的节点个数),同样不为ministers的概率为(son-1)/son。所以没有必要考虑树的结构,直接根句子节点的个数转移dp[i][j]

dp[i][j] = dp[i-1][j-1] * 1 / son[u]

dp[i][j] = dp[i-1][j] * (son[u]-1]) / son[u]

取模的部分可以用逆元。


#include <cstdio>#include <cstring>#include <vector>#include <algorithm>using namespace std;typedef long long ll;const int mod = 1000000007;const int maxn = 1005;int fac[maxn];int N, K, son[maxn];ll dp[maxn][maxn];vector<int> G[maxn];void dfs (int u, int f) {son[u] = 1;for (int i = 0; i < G[u].size(); i++) {int v = G[u][i];if (v == f)continue;dfs(v, u);son[u] += son[v];}}void init () {scanf("%d%d", &N, &K);for (int i = 1; i <= N; i++)G[i].clear();int u, v;for (int i = 1; i < N; i++) {scanf("%d%d", &u, &v);G[u].push_back(v);G[v].push_back(u);}dfs(1, 0);}void exgcd (ll a, ll b, ll& d, ll& x, ll&y) {if (!b)d = a, x = 1, y = 0;else {exgcd(b, a%b, d, y, x);y -= x * (a/b);}}ll inv (ll a) {ll d, x, y;exgcd(a, mod, d, x, y);return d == 1 ? (x + mod) % mod : -1;}int solve () {memset(dp, 0, sizeof(dp));dp[0][0] = 1;for (int i = 1; i <= N; i++) {for (int j = 0; j <= K; j++) {if (dp[i-1][j] == 0)continue;dp[i][j] = (dp[i][j] + dp[i-1][j] * (son[i] - 1) % mod * inv(son[i])) % mod;dp[i][j+1] = (dp[i][j+1] + dp[i-1][j] * inv(son[i])) % mod;}}return dp[N][K] * fac[N] % mod;}int main () {fac[1] = 1;for (int i = 2; i <= 1000; i++)fac[i] = 1LL * i * fac[i-1] % mod;int cas;scanf("%d", &cas);for (int kcas = 1; kcas <= cas; kcas++) {init ();printf("Case #%d: %d\n", kcas, solve());}return 0;}


0 0