Solution:

​ 由于

\[x^m = \sum_{i=0}^m{~m~\choose i}{~x~\brace i}i!
\]

​ 将所求的式子化成这样,挖掘其性质,考虑是否能从儿子转移(或利用以求得信息)。

\[\begin{aligned}
S(u) &= \sum_{i=1}^ndis(u,i)^k\\
&= \sum_{i=1}^n\sum_{j=0}^k{dis(u, i) \choose j}{k\brace j}j!\\
&= \sum_{j=0}^kj!{k\brace j}\sum_{i=1}^n{dis(u, i)\choose j}
\end{aligned}
\]

​ 由于组合数有:\({n\choose m} = {n - 1\choose m - 1} + {n - 1\choose m}\)

​ 而从儿子及父亲到自己的距离为1,于是可以考虑换根树型dp求出每个点的 \(\sum_{i=1}^n{dis(u, i)\choose j}\)

​ 设 \(f[u][j] = \sum_{i}{dis(u, i) \choose j}\) 其中 \(i\) 为 \(u\) 子树中的点。

​ 设 \(g[u][j] = \sum_{i=1}^n{dis(u, i)\choose j}\)

\[f[u][j] = \sum_{v\in son(u)}f[v][j] + f[v][j - 1]\\
g[u][j] = g[fa(u)][j-1]-f[u][j-2]-f[u][j-1]+g[fa(u)][j]-f[u][j-1]-f[u][j]+f[u][j]
\]

Code

  1. #include <vector>
  2. #include <cmath>
  3. #include <cstdio>
  4. #include <cassert>
  5. #include <cstring>
  6. #include <iostream>
  7. #include <algorithm>
  8. typedef long long LL;
  9. typedef unsigned long long uLL;
  10. #define fir first
  11. #define sec second
  12. #define SZ(x) (int)x.size()
  13. #define MP(x, y) std::make_pair(x, y)
  14. #define PB(x) push_back(x)
  15. #define debug(...) fprintf(stderr, __VA_ARGS__)
  16. #define GO debug("GO\n")
  17. #define rep(i, a, b) for (register int i = (a), i##end = (b); (i) <= i##end; ++ (i))
  18. #define drep(i, a, b) for (register int i = (a), i##end = (b); (i) >= i##end; -- (i))
  19. #define REP(i, a, b) for (register int i = (a), i##end = (b); (i) < i##end; ++ (i))
  20. inline int read() {
  21. register int x = 0; register int f = 1; register char c;
  22. while (!isdigit(c = getchar())) if (c == '-') f = -1;
  23. while (x = (x << 1) + (x << 3) + (c xor 48), isdigit(c = getchar()));
  24. return x * f;
  25. }
  26. template<class T> inline void write(T x) {
  27. static char stk[30]; static int top = 0;
  28. if (x < 0) { x = -x, putchar('-'); }
  29. while (stk[++top] = x % 10 xor 48, x /= 10, x);
  30. while (putchar(stk[top--]), top);
  31. }
  32. template<typename T> inline bool chkmin(T &a, T b) { return a > b ? a = b, 1 : 0; }
  33. template<typename T> inline bool chkmax(T &a, T b) { return a < b ? a = b, 1 : 0; }
  34. using namespace std;
  35. const int maxN = 50004;
  36. const int maxK = 153;
  37. const int MOD = 10007;
  38. int n, k;
  39. int fac[maxK];
  40. int stirl[maxK][maxK];
  41. vector<int> ver[maxN];
  42. void Input()
  43. {
  44. n = read(), k = read();
  45. for (int i = 1; i < n; ++i)
  46. {
  47. int u = read(), v = read();
  48. ver[u].push_back(v);
  49. ver[v].push_back(u);
  50. }
  51. }
  52. void Init()
  53. {
  54. fac[0] = 1;
  55. rep (i, 1, k)
  56. fac[i] = 1ll * fac[i - 1] * i % MOD;
  57. stirl[0][0] = stirl[1][1] = 1;
  58. rep (i, 2, k)
  59. rep (j, 1, i)
  60. stirl[i][j] = (1ll * stirl[i - 1][j - 1] + 1ll * j * stirl[i - 1][j] % MOD) % MOD;
  61. }
  62. int f[maxN][maxK], g[maxN][maxK], tmp[maxK];
  63. void dfs1(int u, int fa)
  64. {
  65. f[u][0] = 1;
  66. for (int v : ver[u])
  67. if (v != fa)
  68. {
  69. dfs1(v, u);
  70. f[u][0] = (1ll * f[u][0] + f[v][0]) % MOD;
  71. for (int j = 1; j <= k; ++j)
  72. f[u][j] = ((1ll * f[u][j] + f[v][j]) % MOD + f[v][j - 1]) % MOD;
  73. }
  74. }
  75. void add(int &x, int y)
  76. {
  77. x = (1ll * x + y + MOD) % MOD;
  78. }
  79. void dfs2(int u, int fa)
  80. {
  81. if (!fa)
  82. for (int i = 0; i <= k; ++i) g[u][i] = f[u][i];
  83. else
  84. {
  85. g[u][0] = g[fa][0];
  86. for (int j = 1; j <= k; ++j)
  87. {
  88. int &x = g[u][j];
  89. x = 0;
  90. add(x, g[fa][j]);
  91. add(x, -f[u][j]);
  92. add(x, -f[u][j - 1]);
  93. add(x, g[fa][j - 1]);
  94. add(x, -f[u][j - 1]);
  95. add(x, f[u][j]);
  96. if (j >= 2) add(x, -f[u][j - 2]);
  97. }
  98. }
  99. for (int v : ver[u])
  100. if (v != fa)
  101. dfs2(v, u);
  102. }
  103. void Solve()
  104. {
  105. dfs1(1, 0);
  106. dfs2(1, 0);
  107. for (int i = 1; i <= n; ++i)
  108. {
  109. int ans = 0;
  110. for (int j = 0; j <= k; ++j)
  111. ans = (1ll * ans + 1ll * stirl[k][j] * fac[j] % MOD * g[i][j] % MOD) % MOD;
  112. cout << ans << endl;
  113. }
  114. }
  115. int main()
  116. {
  117. #ifndef ONLINE_JUDGE
  118. freopen("tmp.in", "r", stdin);
  119. freopen("tmp.out", "w", stdout);
  120. #endif
  121. Input();
  122. Init();
  123. Solve();
  124. return 0;
  125. }

[LuoguP1829]Crash的文明表格(二次扫描与换根+第二类斯特林数)的更多相关文章

  1. 【BZOJ2159】Crash的文明世界(第二类斯特林数,动态规划)

    [BZOJ2159]Crash的文明世界(第二类斯特林数,动态规划) 题面 BZOJ 洛谷 题解 看到\(k\)次方的式子就可以往二项式的展开上面考,但是显然这样子的复杂度会有一个\(O(k^2)\) ...

  2. 题解 poj3585 Accumulation Degree (树形dp)(二次扫描和换根法)

    写一篇题解,以纪念调了一个小时的经历(就是因为边的数组没有乘2 phhhh QAQ) 题目 题目大意:找一个点使得从这个点出发作为源点,流出的流量最大,输出这个最大的流量. 以这道题来介绍二次扫描和换 ...

  3. poj 3585 Accumulation Degree(二次扫描和换根法)

    Accumulation Degree 大致题意:有一棵流量树,它的每一条边都有一个正流量,树上所有度数为一的节点都是出口,相应的树上每一个节点都有一个权值,它表示从这个节点向其他出口可以输送的最大总 ...

  4. [国家集训队] Crash 的文明世界(第二类斯特林数)

    题目 [国家集训队] Crash 的文明世界 前置 斯特林数\(\Longrightarrow\)斯特林数及反演总结 做法 \[\begin{aligned} ans_x&=\sum\limi ...

  5. BZOJ 2159: Crash 的文明世界(树形dp+第二类斯特林数+组合数)

    题意 给定一棵 \(n\) 个点的树和一个常数 \(k\) , 对于每个 \(i\) , 求 \[\displaystyle S(i) = \sum _{j=1} ^ {n} \mathrm{dist ...

  6. 【51Nod1405】树上距离和 二次扫描与换根法

    题目大意:给定一棵 N 个点的边权均为 1 的树,依次输出每个点到其他各个点的距离和. 题解:首先任意选定一个节点为根节点,比如 1,第一遍 dfs 遍历树求出子树大小.树上前缀和.第二遍 dfs 遍 ...

  7. 【POJ3585】Accumulation Degree 二次扫描与换根法

    简单来说,这是一道树形结构上的最大流问题. 朴素的解法是可以以每个节点为源点,单独进行一次dp,时间复杂度是\(O(n^2)\) 但是在朴素求解的过程中,相当于每次都求解了一次整棵树的信息,会做了不少 ...

  8. poj3585 树形dp 二次扫描,换根法模板题

    #include<iostream> #include<cstring> #include<cstdio> #include<vector> using ...

  9. POJ3585 Accumulation Degree(二次扫描与换根法)

    题目:http://poj.org/problem?id=3585 很容易想出暴力.那么就先扫一遍. 然后得到了指定一个根后每个点的子树值. 怎么转化利用一下呢?要是能找出当前点的父亲的 “ 不含当前 ...

随机推荐

  1. node开发一个接口详细步骤

    最近在做后台系统改版,由于目前接口还没出来,就自己用nodejs写了个简单的接口. 我这里用的是nodejs+mysql的 这里不讲nodejs和mysql的安装.这些基础略过. 首先创建文件夹.cd ...

  2. Nodejs 学习笔记 --- 安装与环境配置

    一.安装Node.js步骤 1.下载对应自己系统对应的 Node.js 版本,地址:https://nodejs.org/zh-cn/      2.选安装目录进行安装      3.环境配置    ...

  3. 1、获取ip地址

    1.获取ip地址 System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces() .Select(p => p. ...

  4. mysql查询每个部门/班级前几名

    Employee 表包含所有员工信息,每个员工有其对应的 Id, salary 和 department Id . +----+-------+--------+--------------+ | I ...

  5. CF671D Roads in Yusland

    一道很玄妙的题= = 我们考虑先考虑DP 那么有$f[x]=min(c+\sum f[y])$ $f[x]$表示覆盖x的子树和x->fa[x]的所有边最小代价 我们枚举一条边c覆盖的x-> ...

  6. Test 3.27 T2 旅行

    Description FGD 想从成都去上海旅游.在旅途中他希望经过一些城市并在那里欣赏风景,品尝风味小吃或者做其他的有趣的事情.经过这些城市的顺序不是完全随意的,比如说 FGD 不希望在刚吃过一顿 ...

  7. Linux根据进程号查找其程序文件路径 及 lsof 命令使用

    查找进程文件路径 lsof -p pid 1.列出所有打开的文件: lsof 备注: 如果不加任何参数,就会打开所有被打开的文件,建议加上一下参数来具体定位 2. 查看谁正在使用某个文件 lsof   ...

  8. MainRun

    package Testlink; import java.io.IOException; public class MainRun { public static void main(String[ ...

  9. DataTable 转Json格式C#代码

    /// <summary> /// dataTable转换成Json格式 /// </summary> /// <param name="dt"> ...

  10. loj#137 最小瓶颈路 加强版

    分析 我们知道答案一定再最小生成树上 于是我们按边权从小到大建立kruskal重构树 然后每次查询lca的值即可 由于询问较多采用st表维护lca 代码 格式化代码 #include<bits/ ...