「WC 2019」数树

一道涨姿势的EGF好题,官方题解我并没有完全看懂,尝试用指数型生成函数和组合意义的角度推了一波。考场上只得了 44 分也暴露了我在数数的一些基本套路上的不足,后面的 \(\exp\) 是真的神仙,做不出来当然很正常,而且我当时也不怎么会多项式。

Task0

考虑公共边组成 \(k\) 个联通块,答案就是 \(y^k\) ,并查集维护一下即可,复杂度 \(\mathcal O(n\log n)\) 。

code

namespace task0{
map<pair<int, int>, int> mp;
int fa[N];
inline int ask(int x){ return x == fa[x] ? x : fa[x] = ask(fa[x]); }
inline void solve(){
for(int i = 1; i <= n; i++) fa[i] = i;
for(int i = 1, x, y; i <= 2 * (n - 1); i++)
read(x), read(y), mp[make_pair(min(x, y), max(x, y))]++;;
for(map<pair<int, int>, int>::iterator it = mp.begin(); it != mp.end(); it++) if(it->second == 2)
if(ask(it->first.first) != ask(it->first.second)) fa[ask(it->first.first)] = ask(it->first.second);
int tot = 0;
for(int i = 1; i <= n; i++) if(fa[i] == i) tot++;
cout << Pow(Y, tot) << endl;
}
}

Task1

考虑两棵树每有一条公共边,联通块个数就 \(-1\) ,不妨设一开始答案为 \(y^n\) ,每有一条公共边,其对答案的贡献就是 \(z=y^{-1}\) 。

先按照官方题解说的,引入组合恒等式

\[z^k=(z-1+1)^k=\sum_{i=1}^k {k\choose i }(z-1)^i
\]

考虑红树和蓝树的最终形态如果恰好有 \(k\) 条公共边,那么对答案的贡献就是 \(z^k\) ,考虑枚举这种形态的所有公共边的每一个子集,每一个大小为 \(i\) 的子集贡献为 \((z-1)^i\) ,就可以得到这个式子的组合意义。

不妨枚举一个大小为 \(i\) 的公共边集 \(S\) ,(一定是蓝树的一个边集),然后考虑所有公共边集是 \(S\) 的超集的方案,其对答案的贡献就是 \((z-1)^i\) 乘上覆盖它的红树的数量。

假设当前有 \(i\) 条公共边,形成了 \(m=n-i\) 个联通块,其中第 \(i\) 个联通块大小为 \(a_i\) ,根据 \(prufer\) 经典结论 ,可以得到覆盖这个它的红树的数量。

\[n^{m-2}\prod a_i
\]

那么所有情况对答案的贡献和就是

\[n^{-2}\sum_{m=1}^n(z-1)^{n-m}n^m\prod_{\sum_{i=1}^m a_i=n,a_i\geq1} a_i
\]

考虑后面式子的组合意义是在每个联通块中恰好选出一个点的方案数,所以可以令 \(dp[u][0/1]\) 表示蓝树以 \(u\) 为根的联通块是否选出一个点的总贡献,此时每个联通块有 \(n\) 的贡献,每选一条公共边有 \(z\) 的贡献,讨论 \(u\) 的每个儿子是否和 \(u\) 在一个联通块即可,复杂度 \(O(n)\) 。

code

namespace task1{
int dp[N][2], Z;
vector<int> g[N];
inline void dfs(int u, int fa){
dp[u][0] = 1, dp[u][1] = n;
for(int i = 0; i < (int) g[u].size(); i++){
int v = g[u][i];
if(v == fa) continue;
dfs(v, u);
dp[u][1] = (1ll * dp[v][1] * dp[u][1] % P + 1ll * (Z - 1) * (1ll * dp[v][1] * dp[u][0] % P + 1ll * dp[v][0] * dp[u][1] % P) % P) % P;
dp[u][0] = (1ll * dp[v][1] * dp[u][0] % P + 1ll * dp[v][0] * dp[u][0] % P * (Z - 1) % P) % P;
}
}
inline void solve(){
Z = Pow(Y);
for(int i = 1, x, y; i < n; i++){
read(x), read(y);
g[x].push_back(y), g[y].push_back(x);
}
dfs(1, 0);
cout << 1ll * dp[1][1] * Pow(Y, n) % P * Pow(n, P - 3) % P << endl;
}
}

Task 2

还是利用之前的组合恒等式,枚举一个公共边集 \(S\) ,算出其对答案的贡献。

这一步等价于将 \(n\) 拆分成至多 \(m=n-|S|\) 个联通块,每个联通块内部已经固定,计算所有拆分方式对答案的贡献:

\[\sum_{m=1}^n(z-1)^{n-m}\sum_{\sum_{i=1}^{m}a_i=n,a_i\geq1}\dfrac{n!}{m!\prod a_i!} \prod a_i^{a_i-2}\left(n^{m-2}\prod a_i\right)^2
\\
=(z-1)^nn^{-4}\sum_{m=1}^n\sum_{\sum_{i=1}^ma_i=n,a_i\geq1}\dfrac{n!}{m!\prod a_i!}\prod(z-1)^{-1}n^2a_i^{a_i} \\
\]

也就是说每一个大小为 \(a_i\) 的联通块对答案的贡献为 \((z-1)^{-1}n^2a_i^{a_i}\) ,对这些联通块做有标号的集合拼接再乘上之前的系数可以得到答案,前面的 \(\dfrac{n!}{m!\prod a_i!}\) 的组合意义是对于当前枚举的拼接方式,去除集合内部顺序以及拼接顺序的影响后的方案数。

其实到这一步 EGF 的形式就已经很显然了,考虑列出每个联通块的指数型生成函数。

\[f(x) = \sum_{i=1}^{\infty}\dfrac{(z-1)^{-1}n^2i^{i}}{i!}x^i
\]

把这个生成函数 \(\exp\) 一下就自然做完了有标号的集合拼接,前面集合拼接的方案数的系数也不用考虑了。由于 \(\exp\) 后的第 \(n\) 项还有一个 \(\dfrac{x^n}{n!}\) 的形式幂级数要去掉,所以最终式子就变成:

\[(z-1)^nn^{-4}n![x^n]\exp\left(\sum_{i=1}^{\infty}\dfrac{(z-1)^{-1}n^2i^{i}}{i!}x^i\right)
\]

做一遍多项式 \(\exp\) ,注意 \(z = 1\) 也就是 \(y=1\)的时候 \((z-1)^{-1}\) 不存在,需要特判,总复杂度 \(\mathcal O(n \log n)\) 。

code

namespace task2{
int js[N], inv[N], ans[N], f[N];
inline void solve(){
if(Y == 1) return (void) (cout << 1ll * Pow(n, n - 2) * Pow(n, n - 2) % P << endl);
poly::init();
js[0] = inv[0] = 1;
for(int i = 1; i <= n; i++)
js[i] = 1ll * js[i-1] * i % P, inv[i] = Pow(js[i], P - 2);
int Z = Pow(Y, P - 2), c = 1ll * Pow(Z - 1, n) * Pow(n, P - 5) % P * js[n] % P;
int c2 = 1ll * n * n % P * Pow(Z - 1, P - 2) % P;
for(int i = 1; i <= n; i++) f[i] = 1ll * c2 * Pow(i, i) % P * inv[i] % P;
poly::getexp(f, ans, n + 1);
cout << 1ll * ans[n] * c % P * Pow(Y, n) % P;
}
}

「WC 2019」数树的更多相关文章

  1. 【题解】#6622. 「THUPC 2019」找树 / findtree(Matrix Tree+FWT)

    [题解]#6622. 「THUPC 2019」找树 / findtree(Matrix Tree+FWT) 之前做这道题不理解,有一点走火入魔了,甚至想要一本近世代数来看,然后通过人类智慧思考后发现, ...

  2. 「CSP-S 2019」括号树

    [题目描述] 传送门 [题解] 是时候讨论一下我在考场上是怎么将这道题写挂的了 初看这道题毫无思路,先看看部分分吧 一条链的情况?设k[i]表示前i个括号的方案数 显然\(k[i]=k[i-1]+\) ...

  3. 【LOJ】#2983. 「WC2019」数树

    LOJ2983. 「WC2019」数树 task0 有\(i\)条边一样答案就是\(y^{n - i}\) task1 这里有个避免容斥的方法,如果有\(i\)条边重复我们要算的是\(y^{n - i ...

  4. #3146. 「APIO 2019」路灯

    #3146. 「APIO 2019」路灯 题目描述 一辆自动驾驶的出租车正在 Innopolis 的街道上行驶.该街道上有 \(n + 1\) 个停车站点,它们将街道划分成了 \(n\) 条路段.每一 ...

  5. LOJ#3054. 「HNOI 2019」鱼

    LOJ#3054. 「HNOI 2019」鱼 https://loj.ac/problem/3054 题意 平面上有n个点,问能组成几个六个点的鱼.(n<=1000) 分析 鱼题,劲啊. 容易想 ...

  6. #3144. 「APIO 2019」奇怪装置

    #3144. 「APIO 2019」奇怪装置 题目描述 考古学家发现古代文明留下了一种奇怪的装置.该装置包含两个屏幕,分别显示两个整数 \(x\) 和 \(y\). 经过研究,科学家对该装置得出了一个 ...

  7. [Luogu 3701] 「伪模板」主席树

    [Luogu 3701] 「伪模板」主席树 这是一道网络流,不是主席树,不是什么数据结构,而是网络流. 题目背景及描述都非常的暴力,以至于 Capella 在做此题的过程中不禁感到生命流逝. S 向 ...

  8. #3145. 「APIO 2019」桥梁

    #3145. 「APIO 2019」桥梁 题目描述 圣彼得堡市内所有水路长度总和约 282 千米,市内水域面积占城市面积的 7%.--来自维基百科 圣彼得堡位于由 \(m\) 座桥梁连接而成的 \(n ...

  9. Diary / Solution Set -「WC 2022」线上冬眠做噩梦

      大概只有比较有意思又不过分超出能力范围的题叭.   可是兔子的"能力范围" \(=\varnothing\) qwq. 「CF 1267G」Game Relics   任意一个 ...

随机推荐

  1. Hadoop生态圈-Flume的主流Sinks源配置

    Hadoop生态圈-Flume的主流Sinks源配置 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 本篇博客只是配置的是Flume主流的Sinks,想要了解更详细的配置信息请参考官 ...

  2. RESTful记录-RESTful介绍

    RESTful Web服务是基于REST架构的Web服务.在REST架构一切都是一种资源. RESTful Web服务是轻量级的,高度可扩展性和可维护性,并且非常常用于创建基于API的Web应用程序. ...

  3. bzoj千题计划178:bzoj2425: [HAOI2010]计数

    http://www.lydsy.com/JudgeOnline/problem.php?id=2425 题意转化: 给定一个集合S,求S的全排列<给定排列 的排列个数 从最高位开始逐位枚举确定 ...

  4. Mac安装WineHQ

    下载: (链接: https://pan.baidu.com/s/1o7NPhNk 密码: 5227) 安装: 先决条件: XQuartz>=2.7.7 系统设置允许未签名的包. 在https: ...

  5. vue实践中的狗血事件之:mock数据引发的血坑

    在项目实践中,遇到了这么一档子事 开发环境下,很快乐,什么事儿都没有,于是想打包一下测一下自动登录的效果 好家伙,一开始登录没有效,改来改去,最后连路由都切换不了, 明明开发环境下好好的,为毛打包后就 ...

  6. spring如何管理mybatis(一) ----- 动态代理接口

    问题来源 最近在集成spring和mybatis时遇到了很多问题,从网上查了也解决了,但是就是心里有点别扭,想看看到底怎么回事,所以跟了下源码,终于发现了其中的奥妙. 问题分析 首先我们来看看基本的配 ...

  7. Number of Islands I & II

    Given a boolean 2D matrix, find the number of islands. Notice 0 is represented as the sea, 1 is repr ...

  8. 解决windows10 里vs2017 直接开始执行提示“此任务要求应用程序有提升的权限”1.

    1.打开vs的安装路径,我的是 C:\Program Files (x86)\Common Files\Microsoft Shared\MSEnv\ ,找到  VSLauncher.exe 右击该文 ...

  9. C# XML 文档注释

    原文链接:http://www.shinater.com/DocsBuilder/help.html <summary>description</summary> 描述类型或类 ...

  10. springcloud使用使用Feign-Ribbon做负载均衡实现声明式REST调用

    什么是Feign Feign是一个声明式的伪Http客户端,它使得写Http客户端变得更简单.使用Feign,只需要创建一个接口并注解.它具有可插拔的注解特性,可使用Feign 注解和JAX-RS注解 ...