【做题记录】 [HEOI2013]SAO
P4099 [HEOI2013]SAO
类型:树形 \(\text{DP}\)
这里主要补充一下 \(O(n^3)\) 的 \(\text{DP}\) 优化的过程,基础转移方程推导可以参考其他巨佬的博客(题解)。
令 \(f[x][p]\) 表示在以 \(x\) 为根的子树中,\(x\) 在拓扑序排在第 \(p\) 个时的方案数。
转移中设 \(x\) 在已经合并的拓扑序中排名为 \(p_1\) ,将要合并的子树(以 \(ver\) 为根)中 \(ver\) 排名为 \(p_2\) ,合并后 \(x\) 排名为 \(p_3\) 。
列出转移方程:(为了表示方便略去了取模操作)
- 若 \(x < ver\) 即 \(x\) 应在 \(ver\) 之前,\(p_1<p_2\) 。
for(p1 = [1,siz[x]])for(p2 = [1,siz[ver]])for(p3 = [p1,p1+p2-1])f[x][p3]+=f[x][p1]*f[ver][p2]*c[p3-1][p1-1]*c[siz[x]+siz[ver]-p3][siz[x]-p1];
- 若 \(x > ver\) 即 \(x\) 应在 \(ver\) 之后,\(p_1>p_2\) 。
for(p1 = [1,siz[x]])for(p2 = [1,siz[ver]])for(p3 = [p1+p2,siz[x]+siz[ver]])f[x][p3]+=f[x][p1]*f[ver][p2]*c[p3-1][p1-1]*c[siz[x]+siz[ver]-p3][siz[x]-p1];
(更直观的转移方程:)
到此为止,你可以得到 \(40pts\) 的好成绩。
交换内外循环
可以观察到 \(p_2\) 在转移方程中只出现了一次,因此我们将 \(p_2\) 和 \(p_3\) 的循环交换,列出转移方程:
- 若 \(x < ver\) 即 \(x\) 应在 \(ver\) 之前,\(p_1<p_2\) 。
for(p1 = [1,siz[x]])for(p3 = [p1,p1+siz[ver]-1])for(p2 = [p3-p1+1,siz[ver]])f[x][p3]+=f[x][p1]*f[ver][p2]*c[p3-1][p1-1]*c[siz[x]+siz[ver]-p3][siz[x]-p1];
- 若 \(x > ver\) 即 \(x\) 应在 \(ver\) 之后,\(p_1>p_2\) 。
for(p1 = [1,siz[x]])for(p3 = [p1+1,p1+siz[ver]])for(p2 = [1,p3-p1])f[x][p3]+=f[x][p1]*f[ver][p2]*c[p3-1][p1-1]*c[siz[x]+siz[ver]-p3][siz[x]-p1];
前缀和优化去掉一层循环
通过上一步的交换,发现 \(f[x][p3]\) 累加中的 \(p2\) 是一段连续的,并且满足乘法结合律,联想到前缀和优化。
令 \(g[x][p]\) 表示在以 \(x\) 为根的子树中,\(x\) 在拓扑序排在前 \(p\) 个时的方案数之和。
那么转移方程变为:
- 若 \(x < ver\) 即 \(x\) 应在 \(ver\) 之前,\(p_1<p_2\) 。
for(p1 = [1,siz[x]])for(p3 = [p1,p1+siz[ver]-1])g[x][p3]+=g[x][p1]*(g[ver][siz[ver]]-g[ver][p3-p1])*c[p3-1][p1-1]*c[siz[x]+siz[ver]-p3][siz[x]-p1];
- 若 \(x > ver\) 即 \(x\) 应在 \(ver\) 之后,\(p_1>p_2\) 。
for(p1 = [1,siz[x]])for(p3 = [p1+1,p1+siz[ver]])g[x][p3]+=g[x][p1]*g[ver][p3-p1]*c[p3-1][p1-1]*c[siz[x]+siz[ver]-p3][siz[x]-p1];
记得在最后加上:
for(int i=1;i<=siz[x];i++) g[x][i]+=g[x][i-1];
所以这道题 \(AC\) 了。
注:转移中为了维持方程的无后效性,应将 \(f\) 数组备份一遍。
\(100pts\) 完整代码:
#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define Maxn 1005
#define mod 1000000007
inline int rd()
{int x=0;char ch,t=0;while(!isdigit(ch = getchar())) t|=ch=='-';while(isdigit(ch)) x=x*10+(ch^48),ch=getchar();return x=t?-x:x;
}
int t,n,tot;
int dp[Maxn][Maxn],tmp[Maxn],c[Maxn][Maxn],siz[Maxn];
int hea[Maxn],nex[Maxn<<1],ver[Maxn<<1],edg[Maxn<<1];
void add(int x,int y,int d)
{ver[++tot]=y,nex[tot]=hea[x],hea[x]=tot,edg[tot]=d;
}
void dfs(int x,int fa)
{siz[x]=1,dp[x][1]=1;for(int i=hea[x];i;i=nex[i]){if(ver[i]==fa) continue;dfs(ver[i],x);memcpy(tmp,dp[x],sizeof(dp[x]));memset(dp[x],0,sizeof(dp[x]));if(edg[i])for(int p1=1;p1<=siz[x];p1++)for(int p3=p1;p3<=siz[ver[i]]+p1-1;p3++)dp[x][p3]=(dp[x][p3]+1ll*tmp[p1]*(dp[ver[i]][siz[ver[i]]]-dp[ver[i]][p3-p1]+mod)%mod*c[p3-1][p1-1]%mod*c[siz[x]+siz[ver[i]]-p3][siz[x]-p1]%mod)%mod;elsefor(int p1=1;p1<=siz[x];p1++)for(int p3=p1+1;p3<=siz[ver[i]]+p1;p3++)dp[x][p3]=(dp[x][p3]+1ll*tmp[p1]*dp[ver[i]][p3-p1]%mod*c[p3-1][p1-1]%mod*c[siz[x]+siz[ver[i]]-p3][siz[x]-p1]%mod)%mod;siz[x]+=siz[ver[i]];}for(int i=1;i<=siz[x];i++) dp[x][i]=(dp[x][i]+dp[x][i-1])%mod;
}
int main()
{//freopen(".in","r",stdin);//freopen(".out","w",stdout);c[1][0]=c[0][0]=1;for(int i=1;i<=1000;i++,c[i][0]=1)for(int j=1;j<=i;j++)c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;t=rd();char c;while(t--){n=rd();memset(hea,0,sizeof(hea)),tot=0;memset(siz,0,sizeof(siz));for(int i=1,x,y;i<n;i++){x=rd()+1,cin>>c,y=rd()+1;add(x,y,c=='<'),add(y,x,c=='>');}dfs(1,0);printf("%d\n",dp[1][n]);}//fclose(stdin);//fclose(stdout);return 0;
}
【做题记录】 [HEOI2013]SAO相关推荐
- 退役前的做题记录2.0
退役前的做题记录2.0 最近在刷省选题......大致上是按照省份刷的. 不过上面的题目顺序是按照写题的顺序排列的,所以可能会有点乱哈. [BZOJ2823][AHOI2012]信号塔 最小圆覆盖,随 ...
- 概率期望题(期望 DP)做题记录
概率期望题(期望 DP)做题记录 P3830 [SHOI2012]随机树 难点在于第二问:生成树的期望深度. 不 wei zhuo 捏,设 \(dp_{i,j}\) 表示已经有了 \(i\) 个叶子结 ...
- 数数题(计数类 DP)做题记录
数数题(计数类 DP)做题记录 CF1657E Star MST 我们称张无向完全图是美丽的当且仅当:所有和 \(1\) 相连的边的边权之和等于这张完全图的最小生成树的边权之和. 完全图点数为 \(n ...
- CSDN 第六期编程竞赛做题记录
CSDN 第六期编程竞赛做题记录 -- CSDN编程竞赛报名地址:https://edu.csdn.net/contest/detail/16 9.18周日闲来无视写一下 csdn 的编程题,每期编程 ...
- 退役前的做题记录5.0
退役前的做题记录5.0 出于某种原因新开了一篇. [CodeChef]Querying on a Grid 对序列建立分治结构,每次处理\((l,mid,r)\)时,以\(mid\)为源点建立最短路树 ...
- Regional 做题记录 (50/50)
写在前面 博主深感自己太弱了QAQ 于是有了一个刷水的想法,Regional的题目还是有很多考查思维的题目,所以这次是乱做50道思考题,可能会顺带做一些水题,这些题的简要题解会写到这篇博文里面,希望能 ...
- 2020.7月做题记录
转眼就到了2020的下半年了-前方仍是一片茫然. 长期计划 prufer 序列 2020.07.02-2020.07.04 Problem Finished P2624 [HNOI2008]明明的烦恼 ...
- 退役前的做题记录1.0
退役前的做题记录1.0 租酥雨最近很懒qwq,具体表现在写题的时候不想发题解了. 但是想想这样也不太好,就决定发个一句话(半句话到几句话不等)题解上来. 2018-09.18-2018-09.28 [ ...
- 【Pikachu】漏洞练习平台做题记录+原理解析(2.2)XSS姿势和技巧
前言 Pikachu是一个带有漏洞的Web应用系统,在这里包含了常见的web安全漏洞. 如果你是一个Web渗透测试学习人员且正发愁没有合适的靶场进行练习,那么Pikachu可能正合你意. pikach ...
- 退役前的做题记录4.0
退役前的做题记录4.0 最近主要在LOJ上写题 536. 「LibreOJ Round #6」花札 比较显然的二分图博弈模型,先手必胜当且仅当起始点一定在最大匹配中.连边可以对每种颜色以及数字建一个点 ...
最新文章
- Android Hacks:在代码中隐藏软键盘
- C++初始化和关闭roscpp节点
- django makemigrtions时出现no changes detected 解决方式
- linux基础——linux进程间通信(IPC)机制总结
- 17_android下xmlpull解析
- rsync推拉模型及结合inotify实现推模型自动同步
- 盘点程序员开发遇到的30个问题
- super与this关键字的区别
- Qt treeWidget 查找指定字段内容的条目并跳转到该条目
- myVariable是java标识符吗_java 标识符与变量
- HTML5类选择器使用,CSS选择器种类及使用方法
- ProPublica Illinois如何每天使用GNU Make加载1.4GB数据
- Javascript中的内置对象:RegExp对象
- Dom操作(标签--增、删、移动)
- 【毕设】ASP.net校友录毕业设计(源代码+论文+开题报告+答辩PPT)
- jQuery 开始动画,停止动画
- 2021全国研究生数学建模竞赛E题思路
- java驱动刷机_ProductTool(炬力芯片刷机工具+驱动) v5.46 中文安装免费版
- Unparseable date: xxxxxx
- android官方模拟器下载安装,网易MuMu模拟器
热门文章
- zen服务器芯片,服务器版Zen处理器简直大杀器:32核64线程,8通道DDR4内存
- 算法设计与分析——回溯法——n皇后问题
- 算法设计与分析——递归与分治策略——循环日程赛
- 7-3 银行家算法--综合 (50 分)(思路+详解+分析输入)宝宝们 加油
- 网络计算机室电源线怎么布,网吧综合布线(电源和网络)经验谈
- [蓝桥杯2015决赛]积分之迷-枚举(水题)
- 辅助类KeyNode
- PTA天梯赛L1-006 连续因子 (20分)
- 数据结构与算法-- 广度优先打印二叉树
- 广东省计算机媒体大赛,广东省大学生计算机设计大赛