【BZOJ3167】[HEOI2013]SAO(动态规划)
【BZOJ3167】[HEOI2013]SAO(动态规划)
题面
题解
显然限制条件是一个\(DAG\)(不考虑边的方向的话就是一棵树了)。
那么考虑树型\(dp\),设\(f[i][j]\)表示当前点\(i\)在其子树内的排名为\(j\)的方案数。
每次考虑加入一棵子树,即考虑把\(f[v][k]\)加入到\(f[u][i]\)的贡献中。
分类讨论,如果\(v\)应当在\(u\)之前,枚举\(v\)的子树内一共有多少个点在\(u\)之前,那么假设\(u\)当前的序列长度为\(x\),\(v\)当前的序列长度为\(y\),枚举一共有\(j\)个\(v\)的子树内的点在\(u\)之前。
那么此时的方案数就是:\(f[u][i+j]\leftarrow {i+j-1\choose i-1}*f[u][i]*f[v][k]*{y-j+x-i\choose x-i}\)
然后我们来学习枚举(来写假的pascal代码)
for i:=1 to x do
for k:=1 to y do
for j:=k to y do
f[u][i+j]+=f[u][i]*f[v][k]*C[i+j-1][i-1]*C[x+y-i-j][x-i]
似乎这个\(k\)只在\(f[v][k]\)中出现过???
那么我们换一下
for i:=1 to x do
for j:=1 to y do
for k:=1 to j do
f[u][i+j]+=f[u][i]*f[v][k]*C[i+j-1][i-1]*C[x+y-i-j][x-i]
发现把\(f[v]\)数组前缀和一下底下这个玩意就可以做到\(O(1)\)转移啦。
而如果\(v\)要放在\(u\)之后也是类似的。
还是枚举有多少个放在\(u\)之前,那么这一部分的贡献是没变的,只是转移的时候的范围要变一变。
for i:=1 to x do
for k:=1 to y do
for j:=0 to k-1 do
f[u][i+j]+=f[u][i]*f[v][k]*C[i+j-1][i-1]*C[x+y-i-j][x-i]
还是换一下
for i:=1 to x do
for j:=0 to y do
for k:=i+1 to y do
f[u][i+j]+=f[u][i]*f[v][k]*C[i+j-1][i-1]*C[x+y-i-j][x-i]
这样子上面两层循环枚举的都是子树大小,因此全局总的复杂度就是\(O(n^2)\)啦。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define MOD 1000000007
#define MAX 1010
void add(int &x,int y){x+=y;if(x>=MOD)x-=MOD;}
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
struct Line{int v,next,w;}e[MAX<<1];
int h[MAX],cnt;
inline void Add(int u,int v,int w){e[cnt]=(Line){v,h[u],w};h[u]=cnt++;}
void init(){memset(h,0,sizeof(h));cnt=1;}
int n,C[MAX][MAX];char ch[2];
int f[MAX][MAX],sz[MAX],tmp[MAX];
void dfs(int u,int ff)
{
f[u][1]=1;sz[u]=1;
for(int i=h[u];i;i=e[i].next)
{
int v=e[i].v;if(v==ff)continue;
dfs(e[i].v,u);
for(int a=1;a<=sz[u];++a)
for(int b=0;b<=sz[v];++b)
if(e[i].w)
add(tmp[a+b],1ll*f[u][a]*f[v][b]%MOD*C[a+b-1][a-1]%MOD*C[sz[u]+sz[v]-a-b][sz[u]-a]%MOD);
else
add(tmp[a+b],1ll*f[u][a]*(f[v][sz[v]]-f[v][b]+MOD)%MOD*C[a+b-1][a-1]%MOD*C[sz[u]+sz[v]-a-b][sz[u]-a]%MOD);
sz[u]+=sz[v];
for(int j=1;j<=sz[u];++j)f[u][j]=tmp[j],tmp[j]=0;
}
for(int j=1;j<=sz[u];++j)add(f[u][j],f[u][j-1]);
}
int main()
{
for(int i=0;i<MAX;++i)C[i][0]=1;
for(int i=1;i<MAX;++i)
for(int j=1;j<=i;++j)C[i][j]=(C[i-1][j]+C[i-1][j-1])%MOD;
int T=read();
while(T--)
{
init();n=read();
for(int i=1,u,v;i<n;++i)
{
u=read()+1;scanf("%s",ch);v=read()+1;
if(ch[0]=='<')Add(u,v,0),Add(v,u,1);
else Add(u,v,1),Add(v,u,0);
}
dfs(1,0);
printf("%d\n",f[1][n]);
}
return 0;
}
【BZOJ3167】[HEOI2013]SAO(动态规划)的更多相关文章
- bzoj3167 [Heoi2013]Sao
传送门 这题神坑啊……明明是你菜 首先大家都知道原题等价于给每个点分配一个$1$~$n$且两两不同的权值,同时还需要满足一些大于/小于关系的方案数. 先看一眼数据范围,既然写明了$n\le 1000$ ...
- [BZOJ3167][HEOI2013]SAO[树dp+组合数学]
题意 给定 \(n\) 个节点和 \(n-1\) 个限制,每个节点有一个权值,每个限制形如:\(a_i< a_j\) ,问有多少个 \(1\) 到 \(n\) 排列满足要求. \(n\leq 1 ...
- 【BZOJ3167/4824】[Heoi2013]Sao/[Cqoi2017]老C的键盘
[BZOJ3167][Heoi2013]Sao Description WelcometoSAO(StrangeandAbnormalOnline).这是一个VRMMORPG,含有n个关卡.但是,挑战 ...
- 3167: [Heoi2013]Sao [树形DP]
3167: [Heoi2013]Sao 题意: n个点的"有向"树,求拓扑排序方案数 Welcome to Sword Art Online!!! 一开始想错了...没有考虑一个点 ...
- P4099 [HEOI2013]SAO
P4099 [HEOI2013]SAO 贼板子有意思的一个题---我()竟然没看题解 有一张连成树的有向图,球拓扑序数量. 树形dp,设\(f[i][j]\)表示\(i\)在子树中\(i\)拓扑序上排 ...
- BZOJ 3167: [Heoi2013]Sao
3167: [Heoi2013]Sao Time Limit: 30 Sec Memory Limit: 256 MBSubmit: 96 Solved: 36[Submit][Status][D ...
- P4099 [HEOI2013]SAO(树形dp)
P4099 [HEOI2013]SAO 我们设$f[u][k]$表示以拓扑序编号为$k$的点$u$,以$u$为根的子树中的元素所组成的序列方案数 蓝后我们在找一个以$v$为根的子树. 我们的任务就是在 ...
- [HEOI2013]SAO(树上dp,计数)
[HEOI2013]SAO (这写了一个晚上QAQ,可能是我太蠢了吧.) 题目说只有\(n-1\)条边,然而每个点又相互联系.说明它的结构是一个类似树的结构,但是是有向边连接的,题目问的是方案个数,那 ...
- 【做题记录】 [HEOI2013]SAO
P4099 [HEOI2013]SAO 类型:树形 \(\text{DP}\) 这里主要补充一下 \(O(n^3)\) 的 \(\text{DP}\) 优化的过程,基础转移方程推导可以参考其他巨佬的博 ...
随机推荐
- 20分钟 看图手写的table
<html><body><table width="100%" border="1" cellspacing="0&qu ...
- RabbitMQ消息的交换
消息的交换 目录 RabbitMQ-从基础到实战(1)— Hello RabbitMQ RabbitMQ-从基础到实战(2)— 防止消息丢失 1.简介 在前面的例子中,每个消息都只对应一个消费者,即使 ...
- git [command line] fatal: Authentication failed for
fatal: Authentication failed for https://www.jianshu.com/p/8a7f257e07b8 git.exe fetch -v --progress ...
- symfony框架
Symfony是一个完整的框架结构,设计用来帮助并加速网络应用的开发. 1)安装 symfony的安装还是比较简单的,而且提供了多种安装的方式,详情可以看官网手册 问题: cURL error 60: ...
- checkbox的使用总结,判断是否选中
方法一: if ($("#checkbox-id").get(0).checked) { // do something } 方法二: if($('#checkbox-id').i ...
- WebSocket推送
本篇博客只是记录websocket在自己的项目中的应用,只是记录,不做说明(后来替换为GoEasy了). /** * 握手的设置,这其实是为了获取session */ public class Get ...
- [转帖]震惊,用了这么多年的 CPU 利用率,其实是错的
震惊,用了这么多年的 CPU 利用率,其实是错的 2018年12月22日 08:43:09 Linuxer_ 阅读数:50 https://blog.csdn.net/juS3Ve/article/d ...
- oracle常用函数案例
--INSTR函数 SELECT INSTR(' HELLO WORLD','H') FROM DUAL; --LTRIM RTRIM函数 SELECT LTRIM('*HELLO=','*') FR ...
- C# Note17: 使用Ionic.Zip.dll实现解压缩文件
首先下载ionic.Zip.dll,然后在项目中添加该引用,之后就可以在cs中使用了: using Ionic.Zip; #region Ionic.Zip压缩文件 private readonly ...
- 如何使用nodejs快速搭建本地服务器
1.首先要安装好node,js 2.以下有安装包下载的链接:这里的安装包是.msi,如果要其他的,可以到菜鸟教程上去找 32 位安装包下载地址 : https://nodejs.org/dist/v4 ...