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. 多IP加强SSH的安全性

    本文针对一台服务器有多个网卡及IP地址的情况,可以限制某些IP不监听SSH,只允许通过某些IP来登陆 以下配置项在/etc/ssh/sshd_config文件中修改 比如你有4个网卡: eth0 – ...

  2. [SNOI2017]一个简单的询问【莫队+容斥原理】

    题目大意 给你一个数列,让你求两个区间内各个数出现次数的乘积的和. 分析 数据范围告诉我们可以用莫队过. 我并不知道什么曼哈顿什么乱七八糟的东西,但是我们可以用容斥原理将这个式子展开来. \[\sum ...

  3. 【转】无法获得锁 /var/lib/dpkg/lock - open (11: 资源暂时不可用) ubuntu 安装vim 及遇到的错误处理

    今天,处理完问题,闲来无事,打算在虚拟机中的Ubuntu中练习shell脚本编写. 无奈,虚拟机系统所装的只有vi,这个编辑软件对于我们来说还是比较不习惯的,所以打算安装vim.好了,闲言少叙. 安装 ...

  4. 洛谷【P2257】YY的GCD

    YY的GCD 原题链接 这应该是我做的第一道莫比乌斯反演的题目. 题目描述 神犇YY虐完数论后给傻×kAc出了一题 给定N, M,求1<=x<=N, 1<=y<=M且gcd(x ...

  5. Nginx实现负载均衡的几种方式

    负载均衡的几种常用方式 1.轮询(默认) 每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除. upstream backserver { server 192.168 ...

  6. LCOW —— 单一Docker引擎下可同时运行Linux和Windows容器啦!

    https://blog.csdn.net/m2l0zgssvc7r69efdtj/article/details/79251059 就在上周,Docker官方的master分支上新增了LCOW(Li ...

  7. Fiddler 只取所需

    Fiddler每次打开的时候都会打开十多个会话,期望只想抓取自己想要的请求.   1)User Filters:启用过滤器 2)在Filers面板中勾选“Use Filters”,并在Hosts区域, ...

  8. 关于xshell 无法连接虚拟机之我的解决方案

    先说一下我碰到的问题 1,虚拟机配置网络后,并且选的模式是桥接模式,虚拟机中可以访问外网,宿主机中也可以访问外网,虚拟机中可以ping通宿主机,但是宿主机无法ping通虚拟机 解决: 我的原因:我会出 ...

  9. 第二篇-ubuntu18.04下怎么制作GIF动画

    一.在桌面打开终端 二.接着通过apt安装byzanz.sudo apt-get install byzanz 三.安装完成后在终端执行“xwininfo”.xwininfo 四.然后鼠标会变成“+” ...

  10. Day034--Python--锁, 信号量, 事件, 队列, 生产者消费者模型, joinableQueue

    进程同步: 1. 锁 (重点)    锁通常被用来实现对共享资源的同步访问.为每一个共享资源创建一个Lock对象,当你需要访问该资源时,调用acquire方法来获取锁对象(如果其它线程已经获得了该锁, ...