题解 P4827【[国家集训队] Crash 的文明世界】

从阶乘幂到斯特林数 - caijianhong - 博客园 (cnblogs.com)

题目描述

Crash 小朋友最近迷上了一款游戏——文明5 (Civilization V)。在这个游戏中,玩家可以建立和发展自己的国家,通过外交和别的国家交流,或是通过战争征服别的国家。

现在 Crash 已经拥有了一个 \(n\) 个城市的国家,这些城市之间通过道路相连。由于建设道路是有花费的,因此 Crash 只修建了 \(n-1\) 条道路连接这些城市,不过可以保证任意两个城市都有路径相通。

在游戏中,Crash 需要选择一个城市作为他的国家的首都,选择首都需要考虑很多指标,有一个指标是这样的:

\[S(i) = \sum_{j = 1}^{n}{\rm dist}(i, j) ^ k \]

其中 \(S(i)\) 表示第 \(i\) 个城市的指标值,\({\rm dist}(i, j)\) 表示第 \(i\) 个城市到第 \(j\) 个城市需要经过的道路条数的最小值,\(k\) 为一个常数且为正整数。

因此 Crash 交给你一个简单的任务:给出城市之间的道路,对于每个城市,输出这个城市的指标值,由于指标值可能会很大,所以你只需要输出这个数 \(\bmod\ 10007\) 的值。

对于 \(100 \%\) 的数据,\(1\le n\le 5\times 10^4\)\(1\le k\le 150\)

solution

为什么这东西不能直接换根 dp?你考虑你想要的操作无非就是:给你一个集合 \(S\),用

\[\sum_{x\in S}x^k \]

求出

\[\sum_{x\in S}(x+1)^k \]

然而假如你只管 \(k\) 次方的信息,你减一下就会发现

\[(x+1)^k-x^k=\sum_{i=0}^{k-1}\binom k i x^i \]

这个东西是二项式定理形式,展开以后有 \(k\) 项,都比 \(k\) 次要低。这 \(k\) 项你都要维护,维护一项需要 \(O(k)\),合着你需要总共 \(O(k^2)\) 的时间维护信息,过不去。


\((x+1)^k-x^k\) 是一个形如差分的东西,回想起《具体数学》第二章中介绍的有限微积分,其定义

\[\Delta f(x)=f(x+1)-f(x) \]

并发现 \(\Delta x^k\) 没有很好的形式,但是 \(\Delta x^\underline k\)

\[\Delta x^\underline k=(x+1-(x-k+1))x^\underline {k-1}=kx^\underline {k-1} \]

因为我们熟知下降幂与普通幂的转换

\[x^n=\sum_{k}\begin{Bmatrix}n\\ k\end{Bmatrix}x^\underline k \]

加一个求和符号不会影响什么东西

\[\sum_{x\in S}x^n=\sum_{k}\begin{Bmatrix}n\\ k\end{Bmatrix}\sum_{x\in S}x^\underline k \]

那我们就维护 \(\sum_{x\in S}x^\underline k\) 好了,就是所有 \(\leq k\) 次下降阶乘幂都维护一下,这样就能实现我们想要的东西了

\[\sum_{x\in S}(x+1)^\underline k=k\sum_{x\in S}x^\underline {k-1}+\sum_{x\in S}x^\underline k \]

可以 \(O(k)\) 维护出集合中所有数字加一后的信息,可以换根 dp。


\(f_{u, k}\) 维护了 \(\sum_{x\in subtree(u)}x^\underline k\)。记 \(A(f_u)\) 表示将所维护的所有 \(x\) 加一。

转移:\(f_u=\sum_v A(f_v)\),再加上自己的一个 \(0\)(意思是 \(0^\underline k=[k=0]\))。

换根:假设 \(f_u\) 现在拿着是全局的信息,那么将 \(A(f_u-A(f_v))\) 加到 \(f_v\) 上,然后递归 \(v\)

code

#include <bits/stdc++.h>
using namespace std;
#ifdef LOCAL
#define debug(...) fprintf(stderr, ##__VA_ARGS__)
#else
#define endl "\n"
#define debug(...) void(0)
#endif
using LL = long long;
template <class T>
using must_int = enable_if_t<is_integral<T>::value, int>;
template <unsigned umod>
struct modint {/*{{{*/static constexpr int mod = umod;unsigned v;modint() : v(0) {}template <class T, must_int<T> = 0>modint(T x) {x %= mod;v = x < 0 ? x + mod : x;}modint operator+() const { return *this; }modint operator-() const { return modint() - *this; }friend int raw(const modint &self) { return self.v; }friend ostream& operator<<(ostream& os, const modint &self) { return os << raw(self); }modint &operator+=(const modint &rhs) {v += rhs.v;if (v >= umod) v -= umod;return *this;}modint &operator-=(const modint &rhs) {v -= rhs.v;if (v >= umod) v += umod;return *this;}modint &operator*=(const modint &rhs) {v = v * rhs.v % umod;return *this;}modint &operator/=(const modint &rhs) {assert(rhs.v);return *this *= qpow(rhs, mod - 2);}template <class T, must_int<T> = 0>friend modint qpow(modint a, T b) {modint r = 1;for (; b; b >>= 1, a *= a)if (b & 1) r *= a;return r;}friend modint operator+(modint lhs, const modint &rhs) { return lhs += rhs; }friend modint operator-(modint lhs, const modint &rhs) { return lhs -= rhs; }friend modint operator*(modint lhs, const modint &rhs) { return lhs *= rhs; }friend modint operator/(modint lhs, const modint &rhs) { return lhs /= rhs; }bool operator==(const modint &rhs) const { return v == rhs.v; }bool operator!=(const modint &rhs) const { return v != rhs.v; }
};/*}}}*/
using mint = modint<10007>;
int n, k;
mint S[210][210];
valarray<mint> a[50010];
vector<int> g[50010];
valarray<mint> add1(valarray<mint> f) {for (int i = k; i >= 1; i--) f[i] += f[i - 1] * i;return f;
}
mint getValue(const valarray<mint>& f) {mint ret = 0;for (int i = 0; i <= k; i++) ret += S[k][i] * f[i];return ret;
}
void dfs(int u, int fa) {a[u][0] = 1;for (int v : g[u]) if (v != fa) {dfs(v, u);a[u] += add1(a[v]);}
}
void chr(int u, int fa) {for (int v : g[u]) if (v != fa) {a[v] += add1(a[u] - add1(a[v]));chr(v, u);}
}
int main() {
#ifndef LOCALcin.tie(nullptr)->sync_with_stdio(false);  
#endifcin >> n >> k;S[0][0] = 1;for (int i = 1; i <= k; i++) {for (int j = 1; j <= i; j++) S[i][j] = S[i - 1][j] * j + S[i - 1][j - 1];}for (int i = 1; i <= n; i++) a[i].resize(k + 1);for (int i = 1, u, v; i < n; i++) cin >> u >> v, g[u].push_back(v), g[v].push_back(u);dfs(1, 0);chr(1, 0);for (int i = 1; i <= n; i++) cout << getValue(a[i]) << endl;return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/796413.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Nacos】下载和启动

官网说明文档地址:https://nacos.io/docs/latest/quickstart/quick-start/ Nacos 是“易于构建的云原生平台、配置管理和服务管理平台”。这句话,依据我的理解就是:有部署一个分布式环境很复杂,自己搭建框架对技术和能力要求高。所以,站在巨人肩膀上,你只要知道:如何下载…

Docker 之虚悬镜像

虚悬镜像:仓库名、标签都是 虚悬镜像:仓库名、标签都是 <none>​ 的镜像,俗称 dangling image。 在日常工作中,有很小的概率会出现该类镜像,原因可能是 Dockerfile 有问题,或者构建和删除镜像的时候,出现一些错误。 出现了该种镜像后,为了避免造成影响,建议删除…

如何升级用 Helm 安装的极狐GitLab Runner?

本分分享如何对 Helm 安装的 Runner 进行升级。整个过程分为三步:1、确定 Runner 最新版本或者想要升级的版本是否存在;2、用 Helm upgrade 命令进行升级;3、升级确认。 极狐GitLab 为 GitLab 的中国发行版,中文版本对中国用户更友好,可以一键私有化部署,安装升级详情可以…

InfluxDB UI 设置保留策略

InfluxDB UI 设置保留策略 创建Bucket时设置保留策略 在InfluxDB 2.x的UI中创建Bucket时,你可以直接设置其保留策略。以下是一个基本的步骤指南:登录到InfluxDB UI:使用你的凭据登录到InfluxDB 2.x的Web界面。导航到Buckets页面:在左侧菜单中,找到并点击“Buckets”选项。…

Zabbix-Scheduled reports - Cannot connect to web service

最近使用zabbix创建SchedulReport,完成相关配置进行测试时,总是提示创建失败:Cannot connect to web service: couldnt connect to server Cannot connect to web service: couldnt connect to server而且执行cat /var/log/zabbix/zabbix_web_service.log查看zabbix_web_…

PCB设计过程中过孔

按常规过孔 内径12mil 外径24mil计算 计算过流能力kicad:温升5大约1.0A

PbootCMS无缝sqlite数据库转mysql数据库

将 PbootCMS 的 SQLite 数据库无缝转换为 MySQL 数据库,可以遵循以下步骤。请注意,这里所说的“无缝”转换是指尽可能减少数据丢失和格式错误,但仍然需要确保转换后的数据能够正常工作。以下是详细的转换步骤: 1. 导出 SQLite 数据库打开 SQLiteStudio 或类似工具:使用 SQ…

PbootCMS网站模板如何做好防护

为了保护 PbootCMS 网站模板免受攻击和未经授权的访问,可以采取一系列措施来增强其安全性。以下是根据提供的信息整理的一些推荐做法: 1. 更改敏感文件夹名称更改 data 文件夹名称:将 data 文件夹重命名,例如改为 mubanbaba@data。 修改 config/database.php 文件中相应的地…

PbootCMS用户密码重置工具

1、工具作用: 此工具用于忘记PbootCMS后台用户账号密码时进行重置。 2、使用方法: 1)下载重置工具解压包,解压后将resetpw.php文件直接上传到网站根目录下; 2)在浏览器直接访问访问该文件地址,然后按照页面提示输入相关信息进行重置,此处填写的“数据库配置文件”用于重…

小工具:windows测试自己的网络类型

介绍 NatTypeTester是一款NAT路由类型检测工具,测试NAT类型的小工具,方便与各位玩家判断自己网络是否适用于使用STUN内网穿透。 NAT类型一般分成下列4种: 网络类型1. Full Cone NAT (彻底圆锥型)2. Restricted Cone NAT (详细地址限定圆锥型)3. Port Restricted Cone NA…

确保医疗数据完整性:内外网文件摆渡的创新方案!

常见的医疗机构如医院、诊所、疗养院、心理健康服务机构等,在处理患者信息时会涉及到一系列重要的患者信息,这些信息通常包括但不限于如下信息: 基本信息:包括患者的姓名、出生日期、身份证件号码、生物识别信息、住址、电话号码、电子邮箱等,这些信息能够单独或与其他信息…

PbootCMS网站内页打不开提示404的3种常见原因以及解决方法

PbootCMS 网站内页打不开提示 404 错误通常有几种常见的原因及解决方法: 常见原因及解决方法环境配置错误原因:服务器环境配置不当,比如伪静态规则没有正确配置。 解决方法:确认伪静态规则文件是否正确复制到了服务器上。通常伪静态规则文件是 .htaccess(Apache)或 nginx…