[LuoguP1829]Crash的文明表格(二次扫描与换根+第二类斯特林数)

Solution:
由于
\]
将所求的式子化成这样,挖掘其性质,考虑是否能从儿子转移(或利用以求得信息)。
S(u) &= \sum_{i=1}^ndis(u,i)^k\\
&= \sum_{i=1}^n\sum_{j=0}^k{dis(u, i) \choose j}{k\brace j}j!\\
&= \sum_{j=0}^kj!{k\brace j}\sum_{i=1}^n{dis(u, i)\choose j}
\end{aligned}
\]
由于组合数有:\({n\choose m} = {n - 1\choose m - 1} + {n - 1\choose m}\)
而从儿子及父亲到自己的距离为1,于是可以考虑换根树型dp求出每个点的 \(\sum_{i=1}^n{dis(u, i)\choose j}\)
设 \(f[u][j] = \sum_{i}{dis(u, i) \choose j}\) 其中 \(i\) 为 \(u\) 子树中的点。
设 \(g[u][j] = \sum_{i=1}^n{dis(u, i)\choose j}\)
g[u][j] = g[fa(u)][j-1]-f[u][j-2]-f[u][j-1]+g[fa(u)][j]-f[u][j-1]-f[u][j]+f[u][j]
\]
Code
#include <vector>
#include <cmath>
#include <cstdio>
#include <cassert>
#include <cstring>
#include <iostream>
#include <algorithm>
typedef long long LL;
typedef unsigned long long uLL;
#define fir first
#define sec second
#define SZ(x) (int)x.size()
#define MP(x, y) std::make_pair(x, y)
#define PB(x) push_back(x)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define GO debug("GO\n")
#define rep(i, a, b) for (register int i = (a), i##end = (b); (i) <= i##end; ++ (i))
#define drep(i, a, b) for (register int i = (a), i##end = (b); (i) >= i##end; -- (i))
#define REP(i, a, b) for (register int i = (a), i##end = (b); (i) < i##end; ++ (i))
inline int read() {
register int x = 0; register int f = 1; register char c;
while (!isdigit(c = getchar())) if (c == '-') f = -1;
while (x = (x << 1) + (x << 3) + (c xor 48), isdigit(c = getchar()));
return x * f;
}
template<class T> inline void write(T x) {
static char stk[30]; static int top = 0;
if (x < 0) { x = -x, putchar('-'); }
while (stk[++top] = x % 10 xor 48, x /= 10, x);
while (putchar(stk[top--]), top);
}
template<typename T> inline bool chkmin(T &a, T b) { return a > b ? a = b, 1 : 0; }
template<typename T> inline bool chkmax(T &a, T b) { return a < b ? a = b, 1 : 0; }
using namespace std;
const int maxN = 50004;
const int maxK = 153;
const int MOD = 10007;
int n, k;
int fac[maxK];
int stirl[maxK][maxK];
vector<int> ver[maxN];
void Input()
{
n = read(), k = read();
for (int i = 1; i < n; ++i)
{
int u = read(), v = read();
ver[u].push_back(v);
ver[v].push_back(u);
}
}
void Init()
{
fac[0] = 1;
rep (i, 1, k)
fac[i] = 1ll * fac[i - 1] * i % MOD;
stirl[0][0] = stirl[1][1] = 1;
rep (i, 2, k)
rep (j, 1, i)
stirl[i][j] = (1ll * stirl[i - 1][j - 1] + 1ll * j * stirl[i - 1][j] % MOD) % MOD;
}
int f[maxN][maxK], g[maxN][maxK], tmp[maxK];
void dfs1(int u, int fa)
{
f[u][0] = 1;
for (int v : ver[u])
if (v != fa)
{
dfs1(v, u);
f[u][0] = (1ll * f[u][0] + f[v][0]) % MOD;
for (int j = 1; j <= k; ++j)
f[u][j] = ((1ll * f[u][j] + f[v][j]) % MOD + f[v][j - 1]) % MOD;
}
}
void add(int &x, int y)
{
x = (1ll * x + y + MOD) % MOD;
}
void dfs2(int u, int fa)
{
if (!fa)
for (int i = 0; i <= k; ++i) g[u][i] = f[u][i];
else
{
g[u][0] = g[fa][0];
for (int j = 1; j <= k; ++j)
{
int &x = g[u][j];
x = 0;
add(x, g[fa][j]);
add(x, -f[u][j]);
add(x, -f[u][j - 1]);
add(x, g[fa][j - 1]);
add(x, -f[u][j - 1]);
add(x, f[u][j]);
if (j >= 2) add(x, -f[u][j - 2]);
}
}
for (int v : ver[u])
if (v != fa)
dfs2(v, u);
}
void Solve()
{
dfs1(1, 0);
dfs2(1, 0);
for (int i = 1; i <= n; ++i)
{
int ans = 0;
for (int j = 0; j <= k; ++j)
ans = (1ll * ans + 1ll * stirl[k][j] * fac[j] % MOD * g[i][j] % MOD) % MOD;
cout << ans << endl;
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("tmp.in", "r", stdin);
freopen("tmp.out", "w", stdout);
#endif
Input();
Init();
Solve();
return 0;
}
[LuoguP1829]Crash的文明表格(二次扫描与换根+第二类斯特林数)的更多相关文章
- 【BZOJ2159】Crash的文明世界(第二类斯特林数,动态规划)
[BZOJ2159]Crash的文明世界(第二类斯特林数,动态规划) 题面 BZOJ 洛谷 题解 看到\(k\)次方的式子就可以往二项式的展开上面考,但是显然这样子的复杂度会有一个\(O(k^2)\) ...
- 题解 poj3585 Accumulation Degree (树形dp)(二次扫描和换根法)
写一篇题解,以纪念调了一个小时的经历(就是因为边的数组没有乘2 phhhh QAQ) 题目 题目大意:找一个点使得从这个点出发作为源点,流出的流量最大,输出这个最大的流量. 以这道题来介绍二次扫描和换 ...
- poj 3585 Accumulation Degree(二次扫描和换根法)
Accumulation Degree 大致题意:有一棵流量树,它的每一条边都有一个正流量,树上所有度数为一的节点都是出口,相应的树上每一个节点都有一个权值,它表示从这个节点向其他出口可以输送的最大总 ...
- [国家集训队] Crash 的文明世界(第二类斯特林数)
题目 [国家集训队] Crash 的文明世界 前置 斯特林数\(\Longrightarrow\)斯特林数及反演总结 做法 \[\begin{aligned} ans_x&=\sum\limi ...
- BZOJ 2159: Crash 的文明世界(树形dp+第二类斯特林数+组合数)
题意 给定一棵 \(n\) 个点的树和一个常数 \(k\) , 对于每个 \(i\) , 求 \[\displaystyle S(i) = \sum _{j=1} ^ {n} \mathrm{dist ...
- 【51Nod1405】树上距离和 二次扫描与换根法
题目大意:给定一棵 N 个点的边权均为 1 的树,依次输出每个点到其他各个点的距离和. 题解:首先任意选定一个节点为根节点,比如 1,第一遍 dfs 遍历树求出子树大小.树上前缀和.第二遍 dfs 遍 ...
- 【POJ3585】Accumulation Degree 二次扫描与换根法
简单来说,这是一道树形结构上的最大流问题. 朴素的解法是可以以每个节点为源点,单独进行一次dp,时间复杂度是\(O(n^2)\) 但是在朴素求解的过程中,相当于每次都求解了一次整棵树的信息,会做了不少 ...
- poj3585 树形dp 二次扫描,换根法模板题
#include<iostream> #include<cstring> #include<cstdio> #include<vector> using ...
- POJ3585 Accumulation Degree(二次扫描与换根法)
题目:http://poj.org/problem?id=3585 很容易想出暴力.那么就先扫一遍. 然后得到了指定一个根后每个点的子树值. 怎么转化利用一下呢?要是能找出当前点的父亲的 “ 不含当前 ...
随机推荐
- STM32之模拟串口设计
一.设计用途: 公司PCB制成板降成本,选择的MCU比项目需求少一个串口,为满足制成板成本和项目对串口需求,选择模拟一路串口. 二.硬件电路: 三.设计实现: 工具&软件:STM32F030R ...
- FMC141-4路 250Msps/16bits ADC, FMC板卡
FMC141-4路 250Msps/16bits ADC, FMC板卡 一.产品概述: 本板卡基于 FMC 标准板卡,实现 4 路 16-bit/250Msps ADC 功能.遵循 VITA 57 标 ...
- maven_上传到私服,以及从私服下载
公司由于没有maven,自己又想用,于是乎,就自己搭了一个nexus 1.苦逼不多说,将本地jar文件上传到maven 需要在本机(客户端windows)中的maven中的setting.xml添加这 ...
- bzoj3252 攻略 贪心+dfs序+线段树
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3252 题解 有一个非常显然的贪心思路:每次选择目前走到那儿能够获得的新权值最大的点. 证明的话 ...
- 如何使您的Wifi路由器更安全,网络安全专家告诉您!
中国知名“黑客”教父,网络安全专家郭盛华曾说过,Wifi路由器这样设置最安全.因为无线路由器都有不同的接口,不同的设置方式以及可以调整的不同设置.在本文中,我将探讨TP-LinkArcher的界面.您 ...
- R reticulate 设置 python 环境
library("reticulate") use_python("/usr/bin/python", required = T) py_config() 注意 ...
- [LeetCode] 238. 除自身以外数组的乘积 ☆☆☆(左积*右积)
描述 给定长度为 n 的整数数组 nums,其中 n > 1,返回输出数组 output ,其中 output[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积. 示例: 输入: ...
- 使用sys.dm_exec_cached_plans监控存储过程性能
讨论了如何使用sys.dm_exec_query_stats动态管理视图(dmv ).本文将以SQL Server 2005为例,讨论如何利用dmv信息来判断tsql的性能优劣.在这篇文章中将继续我有 ...
- Pycharm创建模板头部默认
PyCharm 打开,点击左上角 “FILE” 进入 “Settings”,进行头文件设置: 如下: 我的模板: #!/usr/bin/env python# -*- coding:utf-8 -*- ...
- spring mvc中的@Entity是什么意思?
@Entitypublic Class JavaBean{}标注该类为实体类.