https://vjudge.net/problem/HDU-4625

题意

给出一颗树,边权为1,对于每个结点u,求sigma(dist(u,v)^k)。

分析

贴个官方题解

n^k并不好转移,于是用第二类斯特林数转化一下,这样可以预处理第二类斯特林数,而sigma(C(dist(u,v),i))则利用C(n,x)=C(n-1,x)+C(n-1,x-1)来进行树DP转移得到。

设dp[u][k]=sigma(C(dist(u,v),k)),则dp[u][k]=dp[v][k]+dp[v][k-1],这里v是u的儿子。先dfs一次算dp值。

接下来再dfs一次,每次以u为根,计算Eu,注意转移时需要将子结点作为新的根,此时需要计算一下合适的dp值。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <ctime>
#include <vector>
#include <queue>
#include <map>
#include <stack>
#include <set>
#include <bitset>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define ms(a, b) memset(a, b, sizeof(a))
#define pb push_back
#define mp make_pair
#define pii pair<int, int>
#define IOS ios::sync_with_stdio(0);cin.tie(0);
#define random(a, b) rand()*rand()%(b-a+1)+a
#define pi acos(-1.0)
const ll INF = 0x3f3f3f3f3f3f3f3fll;
const int inf = 0x3f3f3f3f;
const int maxn = 5e4+;
const int maxm = 1e5+;
const int mod = ;
struct edge{
int t,n;
edge(int t=,int n=):
t(t),n(n){}
}e[maxn<<];
int head[maxn],tot;
void addedge(int u,int v){
e[++tot]=edge(v,head[u]),head[u]=tot;
e[++tot]=edge(u,head[v]),head[v]=tot;
}
int n,k;
int s[][],fac[];
void init(){
s[][]=fac[]=;
for(int i=;i<;i++){
fac[i]=fac[i-]*i%mod;
for(int j=;j<;j++){
s[i][j]=(j*s[i-][j]+s[i-][j-])%mod;
}
}
for(int i=;i<;i++)
for(int j=;j<;j++)
s[i][j]=s[i][j]*fac[j]%mod;
}
int dp[maxn][];
void pre_dfs(int u,int p){
dp[u][]=;
for(int i=;i<=k;i++) dp[u][i]=;
for(int i=head[u];~i;i=e[i].n){
int v = e[i].t;
if(v!=p){
pre_dfs(v,u);
for(int j=;j<=k;j++){
dp[u][j]+=dp[v][j];
if(j) dp[u][j]+=dp[v][j-];
dp[u][j]%=mod;
}
}
}
}
int ans[maxn];
void dfs(int u,int p){
ans[u]=;
for(int i=;i<=k;i++) ans[u]=(ans[u]+s[k][i]*dp[u][i])%mod;
for(int i=head[u];~i;i=e[i].n){
int v=e[i].t;
if(v!=p){
for(int j=;j<=k;j++){
dp[u][j]+=mod-dp[v][j];
if(j) dp[u][j]+=mod-dp[v][j-];
dp[u][j]%=mod;
}
for(int j=;j<=k;j++){
dp[v][j]+=dp[u][j];
if(j) dp[v][j]+=dp[u][j-];
dp[v][j]%=mod;
}
dfs(v,u);
for(int j=;j<=k;j++){
dp[v][j]+=mod-dp[u][j];
if(j) dp[v][j]+=mod-dp[u][j-];
dp[v][j]%=mod;
}
for(int j=;j<=k;j++){
dp[u][j]+=dp[v][j];
if(j) dp[u][j]+=dp[v][j-];
dp[u][j]%=mod;
}
}
}
}
int main(){
#ifdef LOCAL
freopen("in.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
#endif
int t;
scanf("%d",&t);
init();
while(t--){
tot=;
memset(head,-,sizeof head);
int u,v;
scanf("%d%d",&n,&k);
for(int i=;i<n;i++){
scanf("%d%d",&u,&v);
addedge(u,v);
}
pre_dfs(,-);
dfs(,-);
for(int i=;i<=n;i++) printf("%d\n",ans[i]);
}
return ;
}

HDU - 4625 JZPTREE(第二类斯特林数+树DP)的更多相关文章

  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. P4827 [国家集训队] Crash 的文明世界(第二类斯特林数+树形dp)

    传送门 对于点\(u\),所求为\[\sum_{i=1}^ndis(i,u)^k\] 把后面那堆东西化成第二类斯特林数,有\[\sum_{i=1}^n\sum_{j=0}^kS(k,j)\times ...

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

    传送门 解题思路 比较有意思的一道数学题.首先\(n*k^2\)的做法比较好想,就是维护一个\(x^i\)这种东西,然后转移的时候用二项式定理拆开转移.然后有一个比较有意思的结论就是把求\(x^i\) ...

  5. HDU4625 JZPTREE——第二类斯特林数

    复杂度大概O(nk) 一些尝试:1.对每个点推出1,2,3,,,到k次方的值.但是临项递推二项式展开也要考虑到具体每个点的dist 2.相邻k次方递推呢?递推还是不能避免k次方的展开 k次方比较讨厌, ...

  6. hdu 2643 rank 第二类斯特林数

    题意:给定n个人,要求这n个人的所有可能排名情况,可以多个人并列(这个是关键). 题解:由于存在并列的问题,那么对于n个人,我们最多有n个排名,枚举一下1~n,累加一下就好.(注意这里是变种的斯特林数 ...

  7. BZOJ2159 Crash 的文明世界 【第二类斯特林数 + 树形dp】

    题目链接 BZOJ2159 题解 显然不能直接做点分之类的,观察式子中存在式子\(n^k\) 可以考虑到 \[n^k = \sum\limits_{i = 0} \begin{Bmatrix} k \ ...

  8. BZOJ 2159: Crash 的文明世界 第二类斯特林数+树形dp

    这个题非常巧妙啊~ #include <bits/stdc++.h> #define M 170 #define N 50003 #define mod 10007 #define LL ...

  9. 8-机器分配(hud4045-组合+第二类斯特林数)

    http://acm.hdu.edu.cn/showproblem.php?pid=4045 Machine schedulingTime Limit: 5000/2000 MS (Java/Othe ...

随机推荐

  1. 【XSY2767】朋友 广义后缀自动机 网络流

    题目描述 懒得写了...直接贴题面 $\sum n\leq5000,1\leq S_{i,j}\leq k\leq 1000 $ 题解 先建出广义sam. 可以发现朋友的出现位置的定义符合后缀自动机的 ...

  2. bzoj 1854: [Scoi2010]游戏 (并查集||二分图最大匹配)

    链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1854 写法1: 二分图最大匹配 思路:  将武器的属性对武器编号建边,因为只有10000种 ...

  3. Django的Hello World

    Django安装 yum -y install python #安装python yum -y install epel-release #安装扩展源 yum -y install python-pi ...

  4. Codeforces Round #471 (Div. 2) F. Heaps(dp)

    题意 给定一棵以 \(1\) 号点为根的树.若满足以下条件,则认为节点 \(p\) 处有一个 \(k\) 叉高度为 \(m\) 的堆: 若 \(m = 1\) ,则 \(p\) 本身就是一个 \(k\ ...

  5. Before NOIP 2018

    目录 总结 刷题 2018 - 9 - 24 2018 - 9 - 25 2018 - 9 - 26 2018 - 9 - 27 2018 - 9 - 28 2018 - 9 - 29 2018 - ...

  6. Codeforces 700 C. Break Up(Tarjan求桥)

    题意 给你一个有 \(n\) 个点, \(m\) 条边的无向图,每条有边权 \(w_i\) ,现在要选择至多两条边断开,使得 \(S, T\) 不连通,并且使得边权和尽量小. \(n \le 1000 ...

  7. 诶西,JavaScript学习记录。。。。。。

    由于大学课程缘故,老师巨爱叫人问问题,还记分呢,随便记录一下Js的学习情况,以后复习什么的也比较方便吧...... 开始咯,就按照C语言学习那样的方法来吧! ===================== ...

  8. CodeVS1288埃及分数(IDA*)

    在古埃及,人们使用单位分数的和(形如1/a的, a是自然数)表示一切有理数. 如:2/3=1/2+1/6,但不允许2/3=1/3+1/3,因为加数中有相同的. 对于一个分数a/b,表示方法有很多种,但 ...

  9. 【洛谷P1198】最大数

    题目大意:在线维护一个序列,支持插入一个数,查询区间最值. 题解:直接建立线段树,插入就单点修改,查询就正常查..orz开始还真没想到.. 代码如下 #include <bits/stdc++. ...

  10. python学习笔记—Day1

    1. python使用<变量名>=<表达式>的方式对变量进行赋值 a=1; python中数分为整数和浮点数 字符串的定义一定要用引号,单引号和双引号是等价的 三引号用来输入包 ...