P4099 [HEOI2013]SAO


贼板子有意思的一个题~~~我()竟然没看题解

有一张连成树的有向图,球拓扑序数量。

树形dp,设\(f[i][j]\)表示\(i\)在子树中\(i\)拓扑序上排名为\(j\)的方案数。

难就难在转移,现在有两个树\(x\)和\(y\),其中\(x\)是父亲,\(x\)的拓扑序小于\(y\)的,从\(f[x][p1],f[y][p2]\)转移到\(newf[x][p3]\):\(x\)在原序列中排名\(p1\),新序列中\(p3\);\(y\)在原序列中排名\(p2\),新序列中\(p4\),那么限制是\(p3<p4\)

那么\(x\)子树中,\(p1\)左边的点也一定在\(p3\)左边(因为是和同一个点\(x\)比较)

又有限制\(p3<p4\),所以\(y\)的原序列中排名为\([p2,siz_y]\)都在\(p3\)右边,\([1,p2-1]\)可以有一些在\(p3\)右边,有一些在左边

所以\(p3\)的左边数的数量限制是:\(p1-1\leq p3-1\leq p1-1+p2-1\),也就是\(p1\leq p3\leq p1+p2-1\)

\(p3\)的范围就确定了,转移当然还要乘组合数,先考虑左边的情况,左边有\(p3-1\)个点,一定有\(p1-1\)个来自\(x\)的原序列,所以左边的方案数为\(C_{p3-1}^{p1-1}\);右边同理,有\(siz_x+siz_y-p3\)个点,一定有\(siz_x-p1\)个点来自\(x\)的原序列,所以右边方案数是\(C_{siz_x+siz_y-p3}^{siz_x-p1}\)。

综上,从\(f[x][p1],f[y][p2]\)转移到\(newf[x][p3]\),而且新序列中\(x\)在\(y\)左边,要满足\(p1\leq p3\leq p1+p2-1\),转移方程是

\(newf[x][p3]+=C_{p3-1}^{p1-1}C_{siz_x+siz_y-p3}^{siz_x-p1}f[x][p1]f[y][p2]\)

还有一种情况就是新序列中\(x\)在\(y\)右边的,也是同理推,转移方程一样,唯一的区别是\(p3\)的取值范围是\(p1+p2\leq p3\leq p1+siz_x\)。

然后就解决了,然而是\(O(n^3)\)的,考虑优化

当然把式子写出来啊(还是以新序列中\(x\)在\(y\)左边为例)

for p1 in [1,siz_x]
for p2 in [1,siz_y]
for p3 in [p1,p1+p2-1]
转移

观察一下转移方程,好像\(p2\)只出现了一次,还是连续的,于是调换循环顺序(省去对循环范围的推倒):

for p1 in [1,siz_x]
for p3 in [p1,p1+siz_y-1]
for p2 in [p3-p1+1,siz_y]
转移

那么把循环转移成了p2最后一个循环,就可以用前缀和优化转移了,然后这题切了。。。

就是新序列中\(x\)在\(y\)右边的情况直接看代码。

#include<bits/stdc++.h>
#define il inline
#define vd void
#define mod 1000000007
typedef long long ll;
il ll gi(){
ll x=0,f=1;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-')f=-1;
ch=getchar();
}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return x*f;
}
int fir[1010],dis[2010],nxt[2010],w[2010],id;
il vd link(int a,int b,int c){nxt[++id]=fir[a],fir[a]=id,dis[id]=b,w[id]=c;}
int f[1010][1010],g[1010],siz[1010];
int C[1010][1010];
il vd dfs(int x){
siz[x]=1;f[x][1]=1;
for(int i=fir[x];i;i=nxt[i]){
if(siz[dis[i]])continue;
dfs(dis[i]);
memcpy(g,f[x],sizeof g);
memset(f[x],0,sizeof f[x]);
if(w[i]==1){
for(int p1=1;p1<=siz[x];++p1)
for(int p3=p1;p3<p1+siz[dis[i]];++p3)
f[x][p3]=(f[x][p3]+1ll*C[siz[x]+siz[dis[i]]-p3][siz[x]-p1]*C[p3-1][p1-1]%mod*g[p1]%mod*(f[dis[i]][siz[dis[i]]]-f[dis[i]][p3-p1]+mod))%mod;
}else{
for(int p1=1;p1<=siz[x];++p1)
for(int p3=p1+1;p3<=p1+siz[dis[i]];++p3)
f[x][p3]=(f[x][p3]+1ll*C[siz[x]+siz[dis[i]]-p3][siz[x]-p1]*C[p3-1][p1-1]%mod*g[p1]%mod*f[dis[i]][p3-p1])%mod;
}
siz[x]+=siz[dis[i]];
}
for(int i=1;i<=siz[x];++i)f[x][i]=(f[x][i]+f[x][i-1])%mod;
}
int main(){
#ifdef XZZSB
freopen("in.in","r",stdin);
freopen("out.out","w",stdout);
#endif
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-1]+C[i-1][j])%mod;
}
int T=gi();
while(T--){
id=0;memset(fir,0,sizeof fir);memset(siz,0,sizeof siz);
int n=gi(),a,b;char ch;
for(int i=1;i<n;++i){
scanf("%d %c %d",&a,&ch,&b);++a,++b;
link(a,b,ch=='<');link(b,a,ch=='>');
}
dfs(1);
printf("%d\n",f[1][n]);
}
return 0;
}

P4099 [HEOI2013]SAO的更多相关文章

  1. P4099 [HEOI2013]SAO(树形dp)

    P4099 [HEOI2013]SAO 我们设$f[u][k]$表示以拓扑序编号为$k$的点$u$,以$u$为根的子树中的元素所组成的序列方案数 蓝后我们在找一个以$v$为根的子树. 我们的任务就是在 ...

  2. [BZOJ3167][P4099][HEOI2013]SAO(树形DP)

    题目描述 Welcome to SAO ( Strange and Abnormal Online).这是一个 VR MMORPG, 含有 n 个关卡.但是,挑战不同关卡的顺序是一个很大的问题. 有 ...

  3. 洛谷 P4099 - [HEOI2013]SAO(树形 dp)

    题面传送门 题意: 有一个有向图 \(G\),其基图是一棵树 求它拓扑序的个数 \(\bmod (10^9+7)\) \(n \in [1,1000]\) 如果你按照拓扑排序的方法来做,那恐怕你已经想 ...

  4. luogu P4099 [HEOI2013]SAO

    传送门 吐槽题目标题 这个依赖关系是个树,可以考虑树型dp,设f_i表示子树i的答案 因为这是个序列问题,是要考虑某个数的位置的,所以设\(f_{i,j}\)表示子树i构成的序列,i在第j个位置的方案 ...

  5. 洛谷P4099 [HEOI2013]SAO(树形dp)

    传送门 HEOI的题好珂怕啊(各种意义上) 然后考虑树形dp,以大于为例 设$f[i][j]$表示$i$这个节点在子树中排名第$j$位时的总方案数(因为实际只与相对大小有关,与实际数值无关) 我们考虑 ...

  6. 洛谷$P4099\ [HEOI2013]\ SAO\ dp$

    正解:树形$dp$ 解题报告: 传送门$QwQ$. 考虑设$f_i$表示点$i$的子树内的拓扑序排列方案数有多少个. 发现这样不好合并儿子节点和父亲节点.于是加一维,设$f_{i,j}$表示点$i$的 ...

  7. 【做题记录】 [HEOI2013]SAO

    P4099 [HEOI2013]SAO 类型:树形 \(\text{DP}\) 这里主要补充一下 \(O(n^3)\) 的 \(\text{DP}\) 优化的过程,基础转移方程推导可以参考其他巨佬的博 ...

  8. 3167: [Heoi2013]Sao [树形DP]

    3167: [Heoi2013]Sao 题意: n个点的"有向"树,求拓扑排序方案数 Welcome to Sword Art Online!!! 一开始想错了...没有考虑一个点 ...

  9. 【BZOJ3167】[HEOI2013]SAO(动态规划)

    [BZOJ3167][HEOI2013]SAO(动态规划) 题面 BZOJ 洛谷 题解 显然限制条件是一个\(DAG\)(不考虑边的方向的话就是一棵树了). 那么考虑树型\(dp\),设\(f[i][ ...

随机推荐

  1. Java并发编程(一)线程定义、状态和属性

    一 .线程和进程 1. 什么是线程和进程的区别: 线程是指程序在执行过程中,能够执行程序代码的一个执行单元.在java语言中,线程有四种状态:运行 .就绪.挂起和结束. 进程是指一段正在执行的程序.而 ...

  2. recovery 根据@/cache/recovery/block.map描述从data分区升级

    随着android版本的更新,系统固件的大小也越来越大,升级包也越来越大,cache分区已经不够存储update.zip了,所以应用把update.zip下载到data分区,默认情况下data分区是可 ...

  3. 1.Spring MVC详解

    目录 1.SpringMVC 详细介绍 2.SpringMVC 处理请求流程 3.配置前端控制器 4.配置处理器适配器 5.编写 Handler 6.配置处理器映射器 7.配置视图解析器 8.Disp ...

  4. 解决关于phpstorm打开速度很慢的问题

    我的电脑是GTX950M , 8G 内存的 ,配置不算低但是打开phpstorm的速度非常的慢.基本上每次打开都要花一分钟以上,虽然打开sublime text3 只需要三四秒,但是phpstorm功 ...

  5. Alpha冲刺! Day7 - 砍柴

    Alpha冲刺! Day7 - 砍柴 今日已完成 晨瑶:列了各模块目前的进度情况:确定了纯多媒体流星预览页的显示方式:给工具包函数列表新增了与服务器端的交互:玩华为软件云发现刚好可以试试它的测试,于是 ...

  6. asp.net core 如何集成kindeditor并实现图片上传功能

     准备工作 1.visual studio 2015 update3开发环境 2.net core 1.0.1 及以上版本  目录 新建asp.net core web项目 下载kindeditor ...

  7. <20180929>任性的甲方

    今天参观了朋友在监督的新项目, 这个项目周期大概在6到9个月,预计本年度11月竣工. 总共大楼有五层, 施工面积在一万平米左右. 位于三楼的机房使用的设备有点高大上,发上来鉴赏一下. 双专线, 第二条 ...

  8. Windows安装PostgreSQL11.1

    Windows安装PostgreSQL11.1 安装过程如下: 1.下载安装包postgresql-11.1-1-windows-x64.exe 2.点击下一步 3.选择安装位置,默认路径C:\Pro ...

  9. 3D数学读书笔记——矩阵基础

     本系列文章由birdlove1987编写,转载请注明出处.    文章链接:http://blog.csdn.net/zhurui_idea/article/details/24975031   矩 ...

  10. Semaphore实现的生产者消费者程序

    Semaphore:Semaphores are often used to restrict the number of threads than can access some (physical ...