Luogu4827 Crash的文明世界 组合、树形DP
又是喜闻乐见的\(k\)次幂求和题目
那么\(S(x) = \sum\limits_{i=1}^n dist(i,x)^k = \sum\limits_{i=1}^n \sum\limits_{j=1}^k \binom{dist(i,x)}{j} \left\{ \begin{array}{cccc} k \\ j \end{array}\right\} j! = \sum\limits_{j=1}^k \left\{ \begin{array}{cccc} k \\ j \end{array}\right\} j! \sum\limits_{i=1}^n \binom{dist(i,x)}{j}\)。
因为组合数有优秀的性质:\(\binom{i+1}{j}=\binom{i}{j} + \binom{i}{j - 1}\),可以用这一个式子做一个DP。
设\(x\)和\(x\)的子树集合为\(S_x\),\(dp_{i,j}=\sum\limits_{x \in S_i}\binom{dist(i,x)}{j}\),转移的时候考虑\(i\)的孩子\(x\),\(dp_x\)中的所有\(dist\)都会加上\(1\),也就是说\(dp_{i,j} += \sum\limits_{y \in S_x} \binom{dist(x,y)+1}{j} = \sum\limits_{y \in S_x} (\binom{dist(x,y)}{j}+\binom{dist(x,y)}{j-1}) = dp_{x,j}+dp_{x,j-1}\),初始每一个节点\(i\)的\(dp_{i,0}=1\),其余为\(0\)。
接下来设\(up_{i,j} = \sum\limits_{x \not\in S_i}\binom{dist(i,x)}{j}\),转移从一个点\(i\)转移到它的孩子\(x\),将\(dp_x\)对\(dp_i\)的贡献消除之后得到\(dp'_i\),那么不难得到\(up_{x,j} = up_{i,j}+up_{i,j-1}+dp'_{i,j}+dp'_{i,j-1}\)。
最后\(\sum\limits_{i=1}^n \binom{dist(i,x)}{j} = dp_{x,j} + up_{x,j}\)。
#include<bits/stdc++.h>
//this code is written by Itst
using namespace std;
int read(){
int a = 0; char c = getchar();
while(!isdigit(c)) c = getchar();
while(isdigit(c)){
a = a * 10 + c - 48;
c = getchar();
}
return a;
}
const int _ = 50003 , MOD = 10007;
struct Edge{
int end , upEd;
}Ed[_ << 1];
int dp[_][157] , up[_][157] , tmp[157] , S[157][157] , ans[_];
int N , K , head[_] , cntEd;
void addEd(int a , int b){
Ed[++cntEd] = (Edge){b , head[a]};
head[a] = cntEd;
}
void dfs1(int x , int p){//dp
dp[x][0] = 1;
for(int i = head[x] ; i ; i = Ed[i].upEd)
if(Ed[i].end != p){
dfs1(Ed[i].end , x);
for(int j = K ; j ; --j)
dp[x][j] = (dp[x][j] + dp[Ed[i].end][j] + dp[Ed[i].end][j - 1]) % MOD;
dp[x][0] = (dp[x][0] + dp[Ed[i].end][0]) % MOD;
}
}
void dfs2(int x , int p){//up
for(int i = 0 ; i <= K ; ++i)
tmp[i] = (up[x][i] + dp[x][i]) % MOD;
for(int i = head[x] ; i ; i = Ed[i].upEd)
if(Ed[i].end != p){
up[Ed[i].end][0] = (tmp[0] + MOD - dp[Ed[i].end][0]) % MOD;
for(int j = 1 ; j <= K ; ++j)
up[Ed[i].end][j] = (tmp[j] + 2 * MOD - (dp[Ed[i].end][j] + dp[Ed[i].end][j - 1])) % MOD;
for(int j = K ; j ; --j)
up[Ed[i].end][j] = (up[Ed[i].end][j] + up[Ed[i].end][j - 1]) % MOD;
}
for(int i = head[x] ; i ; i = Ed[i].upEd)
if(Ed[i].end != p)
dfs2(Ed[i].end , x);
}
int main(){
#ifndef ONLINE_JUDGE
freopen("in","r",stdin);
//freopen("out","w",stdout);
#endif
N = read(); K = read();
for(int i = 1 ; i < N ; ++i){
int a = read() , b = read();
addEd(a , b); addEd(b , a);
}
S[1][1] = 1;
for(int i = 2 ; i <= K ; ++i)
for(int j = 1 ; j <= i ; ++j)
S[i][j] = (S[i - 1][j - 1] + S[i - 1][j] * j) % MOD;
dfs1(1 , 0); dfs2(1 , 0);
int fac = 1;
for(int j = 1 ; j <= K ; ++j){
fac = 1ll * fac * j % MOD;
for(int i = 1 ; i <= N ; ++i)
ans[i] = (ans[i] + 1ll * (dp[i][j] + up[i][j]) * fac * S[K][j]) % MOD;
}
for(int i = 1 ; i <= N ; ++i)
printf("%d\n" , ans[i]);
return 0;
}
Luogu4827 Crash的文明世界 组合、树形DP的更多相关文章
- BZOJ2159 Crash的文明世界(树形dp+斯特林数)
根据组合意义,有nk=ΣC(n,i)*i!*S(k,i) (i=0~k),即将k个有标号球放进n个有标号盒子的方案数=在n个盒子中选i个将k个有标号球放入并且每个盒子至少有一个球. 回到本题,可以令f ...
- BZOJ 2159: Crash 的文明世界(树形dp+第二类斯特林数+组合数)
题意 给定一棵 \(n\) 个点的树和一个常数 \(k\) , 对于每个 \(i\) , 求 \[\displaystyle S(i) = \sum _{j=1} ^ {n} \mathrm{dist ...
- 【bzoj2159】Crash 的文明世界(树形dp+第二类斯特林数)
传送门 题意: 给出一颗\(n\)个结点的树,对于每个结点输出其答案,每个结点的答案为\(ans_x=\sum_{i=1}^ndis(x,i)^k\). 思路: 我们对于每个结点将其答案展开: \[ ...
- 【BZOJ2159】Crash的文明世界
[2011集训贾志鹏]Crash的文明世界 Description Crash小朋友最近迷上了一款游戏--文明5(Civilization V).在这个游戏中,玩家可以建立和发展自己的国家,通过外交和 ...
- 【BZOJ2159】Crash的文明世界(第二类斯特林数,动态规划)
[BZOJ2159]Crash的文明世界(第二类斯特林数,动态规划) 题面 BZOJ 洛谷 题解 看到\(k\)次方的式子就可以往二项式的展开上面考,但是显然这样子的复杂度会有一个\(O(k^2)\) ...
- [国家集训队] Crash 的文明世界(第二类斯特林数)
题目 [国家集训队] Crash 的文明世界 前置 斯特林数\(\Longrightarrow\)斯特林数及反演总结 做法 \[\begin{aligned} ans_x&=\sum\limi ...
- P4827「国家集训队」 Crash 的文明世界
「国家集训队」 Crash 的文明世界 提供一种不需要脑子的方法. 其实是看洛谷讨论版看出来的( (但是全网也就这一篇这个方法的题解了) 首先这是一个关于树上路径的问题,我们可以无脑上点分治. 考虑当 ...
- BZOJ.2159.Crash的文明世界(斯特林数 树形DP)
BZOJ 洛谷 挺套路但并不难的一道题 \(Description\) 给定一棵\(n\)个点的树和\(K\),边权为\(1\).对于每个点\(x\),求\(S(x)=\sum_{i=1}^ndis( ...
- [BZOJ2159]Crash的文明世界(斯特林数+树形DP)
题意:给定一棵树,求$S(i)=\sum_{j=1}^{n}dist(i,j)^k$.题解:根据斯特林数反演得到:$n^m=\sum_{i=0}^{n}C(n,i)\times i!\times S( ...
随机推荐
- Ajax.BeginForm 不执行OnSuccess
今天用MVC做了一个表单提交,使用Ajax.BeginForm ,但是碰到一个奇怪的问题OnSuccess回调函数不执行.后来经过多次尝试才发现要引用两个东西 1.<script src=&qu ...
- 一篇文章了解Github和Git教程
有趣有内涵的文章第一时间送达! 喝酒I创作I分享 关注我,每天都有优质技术文章推送,工作,学习累了的时候放松一下自己. 本篇文章同步微信公众号 欢迎大家关注我的微信公众号:「醉翁猫咪」 生活中总有些东 ...
- 配置docker阿里云加速器
1. 安装/升级Docker客户端 推荐安装1.10.0以上版本的Docker客户端,参考文档 docker-ce 2. 配置镜像加速器 针对Docker客户端版本大于 1.10.0 的用户 您可以通 ...
- Linux下WebLogic的启动、停止和后台运行的方法
Linux下WebLogic的启动.停止和后台运行的方法 进入目录:/home/weblogic/user_projects/domains/base_domain/bin 查看目录下的命令,如图: ...
- #C++初学记录(STL容器以及迭代器)
STL初步 提交ACM会TLE /仅以学习STL与迭代器使用 C. Cards Sorting time limit per test1 second memory limit per test256 ...
- SpringBoot框架 之 Druid与Swagger2
目录 Druid Druid连接池配置 Druid数据监控 集成Swagger2 Swagger2简介 1.添加依赖 2.创建Swagger2配置类 3.在控制器方法上添加对应api信息 4.启动Sp ...
- 剑指offer:构建乘积数组
题目描述: 给定一个数组A[0,1,...,n-1],请构建一个数组B[0,1,...,n-1],其中B中的元素B[i]=A[0]*A[1]*...*A[i-1]*A[i+1]*...*A[n-1]. ...
- Java_jdbc 基础笔记之六 数据库连接 (PreparedStatement)
reparedStatement 是 Statement 的子接口 * ①需要预编译 SQL 语句:PreparedStatement ps = conn.preparedStatement(sql) ...
- [转]c++多线程编程之pthread线程深入理解
多线程编程之pthread线程深入理解 Pthread是 POSIX threads 的简称,是POSIX的线程标准. 前几篇博客已经能给你初步的多线程概念.在进一 ...
- null undefined NaN
数据类型 6大基本 Number String Boolean Undefined Null. Symbol (ES6) 3大引用类型 object array Function Regexp ...