题目简述:给定$n \leq 50000$个节点的数,每条边的长度为$1$,对每个节点$u$,求

$$ E_u = \sum_{v=1}^n (d(u, v))^k, $$

其中$d(u, v)$是节点$u$和节点$v$的距离,而$k \leq 500$是一个常数。

解1:

斯特林数的性质,我们注意到

$$ x^n = \sum_{k=0}^n \begin{Bmatrix} n \\ k \end{Bmatrix} x^{\underline{k}}. $$

从而,

$$ E_u = \sum_{v=1}^n (d(u, v))^k = \sum_{i=0}^k \begin{Bmatrix} k \\ i \end{Bmatrix} \sum_{v=1}^n (d(u, v))^{\underline{i}}. $$

为此,我们定义

$$f[u][k] = \sum_{v \in T_u} (d(u, v))^{\underline{k}},$$

其中$T_u$表示以$u$为根节点的子树。令$\text{son}(u)$表示节点$u$的所有儿子节点的集合,并注意到$(x+1)^{\underline{k}} = x^{\underline{k}}+kx^{\underline{k-1}}$,则

$$
\begin{aligned}
f[u][k]
& = \sum_{v \in \text{son}(u)} \sum_{w \in T_v} (d(u, w))^{\underline{k}} \\
& = \sum_{v \in \text{son}(u)} \sum_{w \in T_v} (d(v, w)+1)^{\underline{k}} \\
& = \sum_{v \in \text{son}(u)} \sum_{w \in T_v} \Big( (d(v, w))^{\underline{k}}+k (d(v, w))^{\underline{k-1}} \Big) \\
& = \sum_{v \in \text{son}(u)} \Big( f[v][k]+k f[v][k-1] \Big)
\end{aligned}
$$

两遍DFS即可求出所有$E_u$,从而可在$O(nk)$的复杂度内解决。

 #include <bits/stdc++.h>

 using namespace std;

 typedef long long ll;
typedef unsigned long long ull;
typedef double ld;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ld,ld> pdd; #define X first
#define Y second //#include <boost/unordered_map.hpp>
//using namespace boost; /*
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
using namespace __gnu_pbds;
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> rbtree;
rbtree T;
*/ namespace io{
const int L = ( << ) + ; char buf[L], *S , *T, c; char getchar() {
if(__builtin_expect(S == T, )) {
T = (S = buf) + fread(buf, , L, stdin);
return (S == T ? EOF : *S++);
}
return *S++;
} int inp() {
int x = , f = ; char ch;
for(ch = getchar(); !isdigit(ch); ch = getchar())
if(ch == '-') f = -;
for(; isdigit(ch); x = x * + ch - '', ch = getchar());
return x * f;
} unsigned inpu()
{
unsigned x = ; char ch;
for(ch = getchar(); !isdigit(ch); ch = getchar());
for(; isdigit(ch); x = x * + ch - '', ch = getchar());
return x;
} ll inp_ll() {
ll x = ; int f = ; char ch;
for(ch = getchar(); !isdigit(ch); ch = getchar())
if(ch == '-') f = -;
for(; isdigit(ch); x = x * + ch - '', ch = getchar());
return x * f;
} char B[], *outs=B+, *outr=B+;
template<class T>
inline void print(register T a,register char x=){
if(x) *--outs = x, x = ; if(!a)*--outs = '';
else
while(a)
*--outs = (a % ) + , a /= ; if(x)
*--outs = x; fwrite(outs, outr - outs , , stdout);
outs = outr;
}
}; using io :: print;
using io :: inp;
using io :: inpu;
using io :: inp_ll; using i32 = int;
using i64 = long long;
using u8 = unsigned char;
using u32 = unsigned;
using u64 = unsigned long long;
using f64 = double;
using f80 = long double; ll power(ll a, ll b, ll p)
{
if (!b) return ;
ll t = power(a, b/, p);
t = t*t%p;
if (b&) t = t*a%p;
return t;
} ll exgcd(ll a, ll b, ll &x, ll &y)
{
if (b == )
{
x = ;
y = ;
return a;
}
ll px, py;
ll d = exgcd(b, a%b, px, py);
x = py;
y = px-a/b*py;
return d;
} template<class T>
inline void freshmin(T &a, const T &b)
{
if (a > b) a = b;
} template<class T>
inline void freshmax(T &a, const T &b)
{
if (a < b) a = b;
} const int MAXN = ;
const int MAXK = ;
const int MOD = ;
const f80 MI = f80()/MOD;
const int INF = ; int n, k;
int S[MAXK][MAXK]; vector<int> v[MAXN];
int f[MAXN][MAXK], g[MAXN][MAXK]; void dfs1(int x, int p)
{
f[x][] = ;
for (int i = ; i <= k; ++ i)
f[x][i] = ;
for (auto y : v[x])
{
if (y == p) continue;
dfs1(y, x);
(f[x][] += f[y][]) %= MOD;
for (int i = ; i <= k; ++ i)
(f[x][i] += f[y][i]+i*f[y][i-]) %= MOD;
}
} void dfs2(int x, int p)
{
if (!p)
{
for (int i = ; i <= k; ++ i)
g[x][i] = f[x][i];
}
for (auto y : v[x])
{
if (y == p) continue;
g[y][] = g[x][];
for (int i = ; i <= k; ++ i)
{
int g1 = (g[x][i]-(f[y][i]+i*f[y][i-]))%MOD;
int g2 = (g[x][i-]-(f[y][i-]+(i-)*(i- >= ? f[y][i-] : )))%MOD;
g[y][i] = (f[y][i]+g1+i*g2)%MOD;
}
dfs2(y, x);
}
} int main()
{ S[][] = ;
for (int i = ; i <= ; ++ i)
for (int j = ; j <= i; ++ j)
S[i][j] = (S[i-][j-]+S[i-][j]*j)%MOD; for (int T = inp(); T --; )
{
n = inp();
k = inp();
for (int i = ; i <= n; ++ i)
v[i].clear();
for (int i = ; i < n; ++ i)
{
int x = inp();
int y = inp();
v[x].push_back(y);
v[y].push_back(x);
}
dfs1(, );
dfs2(, );
for (int x = ; x <= n; ++ x)
{
int ret = ;
for (int i = ; i <= k; ++ i)
(ret += S[k][i]*g[x][i]) %= MOD;
printf("%d\n", (ret+MOD)%MOD);
}
} return ;
}

解2:

我们用另一个斯特林数的性质:

$$ x^n = \sum_{k=0}^n k! \begin{Bmatrix} n \\ k \end{Bmatrix} \binom{x}{k}. $$

从而,

$$ E_u = \sum_{v=1}^n (d(u, v))^k = \sum_{i=0}^k i! \begin{Bmatrix} k \\ i \end{Bmatrix} \sum_{v=1}^n \binom{d(u, v)}{i}. $$

为此,我们定义

$$f[u][k] = \sum_{v \in T_u} \binom{d(u, v)}{k},$$

其中$T_u$表示以$u$为根节点的子树。令$\text{son}(u)$表示节点$u$的所有儿子节点的集合,则

$$
\begin{aligned}
f[u][k] 
& = \sum_{v \in \text{son}(u)} \sum_{w \in T_v} \binom{d(u, w)}{k} \\
& = \sum_{v \in \text{son}(u)} \sum_{w \in T_v} \binom{d(v, w)+1}{k} \\
& = \sum_{v \in \text{son}(u)} \sum_{w \in T_v} \left( \binom{d(v, w)}{k} + \binom{d(v, w)}{k-1} \right) \\
& = \sum_{v \in \text{son}(u)} \Big( f[v][k]+f[v][k-1] \Big)
\end{aligned}
$$

两遍DFS即可求出所有$E_u$,从而可在$O(nk)$的复杂度内解决。

 #include <bits/stdc++.h>

 using namespace std;

 typedef long long ll;
typedef unsigned long long ull;
typedef double ld;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ld,ld> pdd; #define X first
#define Y second //#include <boost/unordered_map.hpp>
//using namespace boost; /*
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
using namespace __gnu_pbds;
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> rbtree;
rbtree T;
*/ namespace io{
const int L = ( << ) + ; char buf[L], *S , *T, c; char getchar() {
if(__builtin_expect(S == T, )) {
T = (S = buf) + fread(buf, , L, stdin);
return (S == T ? EOF : *S++);
}
return *S++;
} int inp() {
int x = , f = ; char ch;
for(ch = getchar(); !isdigit(ch); ch = getchar())
if(ch == '-') f = -;
for(; isdigit(ch); x = x * + ch - '', ch = getchar());
return x * f;
} unsigned inpu()
{
unsigned x = ; char ch;
for(ch = getchar(); !isdigit(ch); ch = getchar());
for(; isdigit(ch); x = x * + ch - '', ch = getchar());
return x;
} ll inp_ll() {
ll x = ; int f = ; char ch;
for(ch = getchar(); !isdigit(ch); ch = getchar())
if(ch == '-') f = -;
for(; isdigit(ch); x = x * + ch - '', ch = getchar());
return x * f;
} char B[], *outs=B+, *outr=B+;
template<class T>
inline void print(register T a,register char x=){
if(x) *--outs = x, x = ; if(!a)*--outs = '';
else
while(a)
*--outs = (a % ) + , a /= ; if(x)
*--outs = x; fwrite(outs, outr - outs , , stdout);
outs = outr;
}
}; using io :: print;
using io :: inp;
using io :: inpu;
using io :: inp_ll; using i32 = int;
using i64 = long long;
using u8 = unsigned char;
using u32 = unsigned;
using u64 = unsigned long long;
using f64 = double;
using f80 = long double; ll power(ll a, ll b, ll p)
{
if (!b) return ;
ll t = power(a, b/, p);
t = t*t%p;
if (b&) t = t*a%p;
return t;
} ll exgcd(ll a, ll b, ll &x, ll &y)
{
if (b == )
{
x = ;
y = ;
return a;
}
ll px, py;
ll d = exgcd(b, a%b, px, py);
x = py;
y = px-a/b*py;
return d;
} template<class T>
inline void freshmin(T &a, const T &b)
{
if (a > b) a = b;
} template<class T>
inline void freshmax(T &a, const T &b)
{
if (a < b) a = b;
} const int MAXN = ;
const int MAXK = ;
const int MOD = ;
const f80 MI = f80()/MOD;
const int INF = ; int n, k;
int S[MAXK][MAXK]; vector<int> v[MAXN];
int f[MAXN][MAXK], g[MAXN][MAXK]; void dfs1(int x, int p)
{
f[x][] = ;
for (int i = ; i <= k; ++ i)
f[x][i] = ;
for (auto y : v[x])
{
if (y == p) continue;
dfs1(y, x);
(f[x][] += f[y][]) %= MOD;
for (int i = ; i <= k; ++ i)
(f[x][i] += f[y][i]+f[y][i-]) %= MOD;
}
} void dfs2(int x, int p)
{
if (!p)
{
for (int i = ; i <= k; ++ i)
g[x][i] = f[x][i];
}
for (auto y : v[x])
{
if (y == p) continue;
g[y][] = g[x][];
for (int i = ; i <= k; ++ i)
{
int g1 = (g[x][i]-(f[y][i]+f[y][i-]))%MOD;
int g2 = (g[x][i-]-(f[y][i-]+(i- >= ? f[y][i-] : )))%MOD;
g[y][i] = (f[y][i]+g1+g2)%MOD;
}
dfs2(y, x);
}
} int main()
{ S[][] = ;
for (int i = ; i <= ; ++ i)
for (int j = ; j <= i; ++ j)
S[i][j] = (S[i-][j-]+S[i-][j]*j)%MOD; for (int T = inp(); T --; )
{
n = inp();
k = inp();
for (int i = ; i <= n; ++ i)
v[i].clear();
for (int i = ; i < n; ++ i)
{
int x = inp();
int y = inp();
v[x].push_back(y);
v[y].push_back(x);
}
dfs1(, );
dfs2(, );
for (int x = ; x <= n; ++ x)
{
int ret = ;
int fact = ;
for (int i = ; i <= k; ++ i)
{
(ret += S[k][i]*fact%MOD*g[x][i]) %= MOD;
(fact *= i+) %= MOD;
}
printf("%d\n", (ret+MOD)%MOD);
}
} return ;
}

HDU 4625. JZPTREE的更多相关文章

  1. bzoj 2159 Crash 的文明世界 && hdu 4625 JZPTREE ——第二类斯特林数+树形DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2159 学习材料:https://blog.csdn.net/litble/article/d ...

  2. bzoj 2159 Crash 的文明世界 & hdu 4625 JZPTREE —— 第二类斯特林数+树形DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2159 使用公式:\( n^{k} = \sum\limits_{i=0}^{k} S(k,i ...

  3. HDU - 4625 JZPTREE(第二类斯特林数+树DP)

    https://vjudge.net/problem/HDU-4625 题意 给出一颗树,边权为1,对于每个结点u,求sigma(dist(u,v)^k). 分析 贴个官方题解 n^k并不好转移,于是 ...

  4. hdu 4625 Dice(概率DP)

    Dice Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submi ...

  5. 学习总结:斯特林数( Stirling number )

    基本定义 第一类斯特林数:$1 \dots n$的排列中恰好有$k$个环的个数:或是,$n$元置换可分解为$k$个独立的轮换的个数.记作 $$ \begin{bmatrix} n \\ k \end{ ...

  6. Solution Set - Stirling 数相关杂题

      <好多题的题解>   「洛谷 P5408」第一类斯特林数·行   根据结论 \[x^{\overline{n}}=\sum_i{n\brack i}x^i, \] 我们只需要求出 \( ...

  7. HDOJ 2111. Saving HDU 贪心 结构体排序

    Saving HDU Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  8. 【HDU 3037】Saving Beans Lucas定理模板

    http://acm.hdu.edu.cn/showproblem.php?pid=3037 Lucas定理模板. 现在才写,noip滚粗前兆QAQ #include<cstdio> #i ...

  9. hdu 4859 海岸线 Bestcoder Round 1

    http://acm.hdu.edu.cn/showproblem.php?pid=4859 题目大意: 在一个矩形周围都是海,这个矩形中有陆地,深海和浅海.浅海是可以填成陆地的. 求最多有多少条方格 ...

随机推荐

  1. WPF之DataGrid篇:DataGridComboBoxColumn

    准备数据源   1 准备数据源.基类为Student,数据对象为Student3,数据集为StuList3. END 编辑DataGrid显示列   1 若要填充下拉列表,请首先使用下列选项之一设置 ...

  2. BeeFramework 系列二 UISignal篇下

    本文转载至 http://www.apkbus.com/android-126129-1-1.html     qihoo2 该用户从未签到 156 主题 156 帖子 1826 积分 Android ...

  3. 设计TCP服务器的规则

    设计TCP服务器,采用如下规则: 1.正等待连接请求的一端有一个固定长度的连接队列,该队列中的连接已被TCP接受(完成三次握手),但还没有被应用层接受.注意:TCP接受一个连接是将其放入这个队列,而应 ...

  4. poj 2151Check the difficulty of problems<概率DP>

    链接:http://poj.org/problem?id=2151 题意:一场比赛有 T 支队伍,共 M 道题, 给出每支队伍能解出各题的概率~  求 :冠军至少做出 N 题且每队至少做出一题的概率~ ...

  5. Java 内存分配全面浅析(转)

    本文将由浅入深详细介绍Java内存分配的原理,以帮助新手更轻松的学习Java.这类文章网上有很多,但大多比较零碎.本文从认知过程角度出发,将带给读者一个系统的介绍. 进入正题前首先要知道的是Java程 ...

  6. gridcontrol 之标题 GroupPanel设置 (标题设置,屏蔽右键)

    GroupPanel设置 例如gridcontrol显示标题:“gridcontrol小例子” gridView1.GroupPanelText="gridcontrol小例子"; ...

  7. 九度OJ 1037:Powerful Calculator(强大的计算器) (大整数运算)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:1821 解决:528 题目描述: Today, facing the rapid development of business, SJTU ...

  8. 九度OJ 1035:找出直系亲属 (二叉树、递归)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:2380 解决:934 题目描述:     如果A,B是C的父母亲,则A,B是C的parent,C是A,B的child,如果A,B是C的(外) ...

  9. 【题解】 CF11D A Simple Task

    [题解] CF11D A Simple Task 传送门 \(n \le 20\) 考虑状态压缩\(dp\). 考虑状态,\(dp(i,j,O)\)表示从\(i\)到\(j\)经过点集\(O\)的路径 ...

  10. okhttp 请求list数据实例

    public class DataBean { /** * id : 61684 * movieName : <猜火车2>先导预告片 * coverImg : http://img31.m ...