UOJ Round #20 T1 A. 【UR #20】跳蚤电话(组合数+树形DP)
UOJ Round #20 T1 A. 【UR #20】跳蚤电话
题目大意
- 给出一棵树,求建出该树的不同操作方案数。建树方式如下:初始 S S S集合只有 1 1 1,操作 1 1 1为取已连的边 x , y x,y x,y和不在 S S S的点 z z z,删去边 ( x , y ) (x,y) (x,y),加入边 ( x , z ) , ( y , z ) (x,z),(y,z) (x,z),(y,z),再把 z z z放入 S S S;操作 2 2 2为取 S S S内的点 x x x和 S S S外的点 y y y,加入边 ( x , y ) (x,y) (x,y),再把 y y y放入 S S S。
- 2 ≤ n ≤ 1 0 5 2\le n \le 10^5 2≤n≤105
题解
- 可以先分析操作,得出一些结论:
- 1、 x ∈ S x\in S x∈S当且仅当 x x x与 1 1 1连通;
- 2、 S S S能在操作中出现(即合法)当且仅当 S S S中任意两点的 l c a lca lca也在 S S S中;
- 3、任意一个合法的 S S S,只对应唯一一种树的形态,因此操作实质是按一定顺序不断加点;
- 4、某个子树内的点的加入顺序与子树外无关。
- 于是可以考虑树形DP,设 f i f_i fi表示 i i i子树内的不同顺序方案数,有两种转移。
- 一、先加入子树根,再儿子内所有点保持各自相对顺序插入(用组合数);
- 二、先加入某个儿子的部分点(枚举数量),再加入子树根,最后把该儿子剩下的点和其他儿子内所有点保持各自相对顺序插入。(当 i i i为 1 1 1时不能使用这种转移)
- 写出来后发现很多式子都是可以优化的。最后有一个部分式子形如 ( m 0 ) + ( m + 1 1 ) + ( m + 2 2 ) + . . . + ( m + k k ) {m\choose0}+{m+1\choose1}+{m+2\choose2}+...+{m+k\choose k} (0m)+(1m+1)+(2m+2)+...+(km+k),可以把 ( m 0 ) m\choose 0 (0m)看做是 ( m + 1 0 ) m+1\choose 0 (0m+1),然后在杨辉三角上就能不断合并下来,最后结果是 ( m + k + 1 k ) m+k+1\choose k (km+k+1)。
- 由于快速幂,最后复杂度是 O ( n log n ) O(n\log n) O(nlogn)。
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 100010
#define md 998244353
#define ll long long
int last[N], nxt[N * 2], to[N * 2], len = 0;
int si[N], f[N];
ll F[N], G[N];
int ans = 0;
ll ksm(ll x, ll y) {if(!y) return 1;ll l = ksm(x, y / 2);if(y % 2) return l * l % md * x % md;return l * l % md;
}
ll C(int x, int y) {return F[x] * G[y] % md * G[x - y] % md;
}
void add(int x, int y) {to[++len] = y;nxt[len] = last[x];last[x] = len;
}
void dfs(int k, int fa) {si[k] = 1;ll sum = 1;for(int i = last[k]; i; i = nxt[i]) if(to[i] != fa) {dfs(to[i], k);si[k] += si[to[i]];sum = sum * C(si[k] - 1, si[to[i]]) % md * f[to[i]] % md;}f[k] = sum;if(k == 1) return;for(int i = last[k]; i; i = nxt[i]) if(to[i] != fa) {int x = to[i];ll s = C(si[k] - 1, si[x] - 1);ll t = f[x] * sum % md * ksm(f[x] * C(si[k] - 1, si[x]) % md, md - 2) % md;f[k] = (f[k] + s * t % md) % md;}
}
int main() {int n, i, x, y;scanf("%d", &n);F[0] = G[0] = 1;for(i = 1; i <= n; i++) F[i] = F[i - 1] * i % md;G[n] = ksm(F[n], md - 2);for(i = n - 1; i; i--) G[i] = G[i + 1] * (i + 1) % md;for(i = 1; i < n; i++) {scanf("%d%d", &x, &y);add(x, y), add(y, x);}dfs(1, 0);printf("%lld\n", f[1]);return 0;
}
自我小结
- 从头到尾想法都比较自然,思路还是很清晰的,但是式子在实现上容易出现细节问题。
UOJ Round #20 T1 A. 【UR #20】跳蚤电话(组合数+树形DP)相关推荐
- Codeforces Round #263 (Div. 2) D. Appleman and Tree(树形DP)
题目链接 D. Appleman and Tree time limit per test :2 seconds memory limit per test: 256 megabytes input ...
- 根据商品类型按商品价格对商品打标签。标签规则:前20%为高档,20%到80%为中档,后20%为低档。
考点:窗口函数与case when 题目:根据商品类型按商品价格对商品打标签.标签规则:前20%为高档,20%到80%为中档,后20%为低档. 1.建表: CREATE TABLE IF NOT EX ...
- 20.27 分发系统介绍 20.28 expect脚本远程登录 20.29 expect脚本远程执行
20.27 分发系统介绍 20.28 expect脚本远程登录 20.29 expect脚本远程执行命令 20.30 expect脚本传递参数 20.27 分发系统介绍 分发系统,什么叫分发系统,首先 ...
- 30岁是全新的20岁?---《20岁时光不再来》
TED最火的视频之一<20岁时光不再来>的分享者Meg Jay是一名心理咨询师.她的第一位咨询者是一位20多岁的姑娘,而这个姑娘正在和一个"渣男"谈恋爱,并深陷其中. ...
- 根据当前日期进行以下方面的处理: 1、取得日期的年份、月份、天、时、分、秒,并转换成大写日期格式 如:2013年8月17日 20时30分20秒 2、根据日期的不同时间段,做问候语: 早上8:00-12
根据当前日期进行以下方面的处理: 1.取得日期的年份.月份.天.时.分.秒,并转换成大写日期格式 如:2013年8月17日 20时30分20秒 2.根据日期的不同时间段,做问候语: 早上8:00-12 ...
- 关于char str[20]=““ 和 char str[20]=“ “
如题,定义一个长度为20的字符串,区别在于一个双引号中什么也没有,而另一个双引号中有一个空格.为了方便知道数组中存入的字符串究竟是什么,我们用调试功能,查看str数组中究竟是什么. 这是 str[20 ...
- 【Christmas Game】【CodeCraft-21 and Codeforces Round #711 (Div. 2)】【Nim-博弈】【树形DP】【拆分树】
CodeCraft-21 and Codeforces Round #711 (Div. 2) Christmas Game Nim-博弈 树形DP 拆分树 牛客链接 https://ac.nowco ...
- UOJ #131 BZOJ 4199 luogu P2178【NOI2015】品酒大会 (后缀自动机、树形DP)
UOJ #131 BZOJ 4199 luogu P2178[NOI2015]品酒大会 (后缀自动机.树形DP) 水是水,但是写出了不少问题,因此写一发博客. https://www.luogu.or ...
- [BZOJ3677/UOJ#105][APIO2014]Beads and wires 连珠线(树形dp+换根)
Address https://www.lydsy.com/JudgeOnline/problem.php?id=3677 http://uoj.ac/problem/105 Solution 考虑一 ...
最新文章
- 跨域问题汇总【已收录 CORS JSONP】
- python fact函数_第5天:Python 函数
- C#通过DllImport引入dll中的C++非托管类
- .NET 现代化动态 LINQ 库 Gridify
- Win 11 真的要来了!微软宣布 Win10 将于 2025 年终止支持!
- 爱因斯坦留下的预言还有几个未实现?
- jQuery UI加入效果
- Hibernate面试题收藏
- 8个JavaScript题目
- CCKS 2018 | 最佳论文:南京大学提出DSKG,将多层RNN用于知识图谱补全
- java21天打卡-day14 日期时间
- 元数据(MetaData)
- java中递归算法_java中递归算法是什么怎么算的?
- 计算机网络攻防技术的分析与研究
- opencapwap简要分析
- 【夜读】有些人注定不会失败
- OpenBot开源小车
- 石墨文档 Websocket 百万长连接技术实践
- 详解SQL中几种常用的表连接方式!
- 计算机在职研究生分数,在职研究生复试录取分数线-在职研招网-在职研究生招生信息网...