HDU 4625. JZPTREE
题目简述:给定$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的更多相关文章
- bzoj 2159 Crash 的文明世界 && hdu 4625 JZPTREE ——第二类斯特林数+树形DP
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2159 学习材料:https://blog.csdn.net/litble/article/d ...
- 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 ...
- HDU - 4625 JZPTREE(第二类斯特林数+树DP)
https://vjudge.net/problem/HDU-4625 题意 给出一颗树,边权为1,对于每个结点u,求sigma(dist(u,v)^k). 分析 贴个官方题解 n^k并不好转移,于是 ...
- hdu 4625 Dice(概率DP)
Dice Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Total Submi ...
- 学习总结:斯特林数( Stirling number )
基本定义 第一类斯特林数:$1 \dots n$的排列中恰好有$k$个环的个数:或是,$n$元置换可分解为$k$个独立的轮换的个数.记作 $$ \begin{bmatrix} n \\ k \end{ ...
- Solution Set - Stirling 数相关杂题
<好多题的题解> 「洛谷 P5408」第一类斯特林数·行 根据结论 \[x^{\overline{n}}=\sum_i{n\brack i}x^i, \] 我们只需要求出 \( ...
- HDOJ 2111. Saving HDU 贪心 结构体排序
Saving HDU Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total ...
- 【HDU 3037】Saving Beans Lucas定理模板
http://acm.hdu.edu.cn/showproblem.php?pid=3037 Lucas定理模板. 现在才写,noip滚粗前兆QAQ #include<cstdio> #i ...
- hdu 4859 海岸线 Bestcoder Round 1
http://acm.hdu.edu.cn/showproblem.php?pid=4859 题目大意: 在一个矩形周围都是海,这个矩形中有陆地,深海和浅海.浅海是可以填成陆地的. 求最多有多少条方格 ...
随机推荐
- python 基础 4.0 函数的一般形式及传参
#/usr/bin/python #coding=utf-8 #@Time :2017/10/23 15:58 #@Auther :liuzhenchuan #@File :函数的一般形式.p ...
- Linuxt图形界面安装
通常安装图形界面需要安装Xorg.桌面环境(Gnome.KDE.xfce等).字体等.你的Linux是什么版本?具体要看你的linux来决定用什么命令来安装. #yum grouplist 自己看看列 ...
- 一些重要的地址:md5在线解密破解
md5在线解密破解:https://www.cmd5.com/
- centos 安装postgresql 完整版
按步骤 执行命令即可: yum install https://download.postgresql.org/pub/repos/yum/10/redhat/rhel-7-x86_64/pgdg-c ...
- 【C语言天天练(十)】结构体
引言:数据常常以成组的形式存在.在C中,使用结构能够把不同类型的值存放在一起. 结构的声明有两种 1.struct SIMPLE{ int a; char b; float c; };然后用标签SIM ...
- Swift语言概览
Swift语言概览 关于 这篇文章简要介绍了苹果于WWDC 2014公布的编程语言--Swift. 前言 在这里我觉得有必要提一下Brec Victor的Invent ...
- MySQL——事务
核心知识: 1.什么是事务?一组原子性的SQL查询语句 2.事务的四种属性:ACID 3.四种隔离级别:读取未提交内容.读取提交内容.重复读.串行化. 4.什么是幻读?幻读有那些解决办法?连续读取同一 ...
- Java for LeetCode 084 Largest Rectangle in Histogram【HARD】
For example, Given height = [2,1,5,6,2,3], return 10. 解题思路: 参考Problem H: Largest Rectangle in a Hist ...
- linux下 python源码包解压报错
执行下面的命令 tar -zvxf Python.3.6.5.tgz 报错 gzip: stdin: not in gzip format tar: Child returned status 1 t ...
- 微信小程序开发:学习笔记[4]——样式布局
微信小程序开发:学习笔记[4]——样式布局 Flex布局 新的布局方式 在小程序开发中,我们需要考虑各种尺寸终端设备上的适配.在传统网页开发,我们用的是盒模型,通过display:inline | b ...