bzoj3167 [Heoi2013]Sao
这题神坑啊……明明是你菜
首先大家都知道原题等价于给每个点分配一个$1$~$n$且两两不同的权值,同时还需要满足一些大于/小于关系的方案数。
先看一眼数据范围,既然写明了$n\le 1000$,那就应该是什么$O(n^2)$的做法了。显然这个东西只能是个DP,考虑到题中给出的是一个树形结构,那么就可以利用子树的相对独立性进行DP:设$f_{i,j}$表示以$i$为根的子树中有$j$个点的权值大于$i$的权值时的方案数,显然最终答案就是$\sum_{i}f_{root,i}$。
然后考虑怎么求出答案。通常树形DP都是自底向上逐个合并来得到每个点的DP值的,但注意这个DP无法做到像普通的树形DP一样可以快速(比如$O(1)$或者$O(\log^2 n)$之类)合并。不过这个DP还是可以比较高效地合并的,设要合并的两个子树大小分别为$n,m$,那么我们就可以通过枚举每一对$(i,j)$对应的$f_{\dots,i}$和$f_{\dots,j}$对合并后的DP数组的贡献来在$O(nm)$的时间内得到它们合并后的DP数组。
具体的合并过程就不写了,大体思路是先枚举最后$i$的权值在整个子树中的排名,然后枚举另一棵子树中有几个点权值比$i$的权值小,最后换元得到枚举$(i,j)$的形式。顺便一提,这个DP方程还需要一个前缀和优化才能做到$O(nm)$合并,还有大于和小于两种情况需要分开处理。
/**************************************************************
Problem: 3167
User: _Angel_
Language: C++
Result: Accepted
Time:3984 ms
Memory:8792 kb
****************************************************************/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=,p=;
int C[maxn][maxn];
struct DP{
int f[maxn],n;
void clear(){
memset(f,,sizeof(f));
n=;
f[]=;
}
DP &operator+=(const DP &b){
static int g[maxn];
memset(g,,sizeof(g));
for(int i=;i<n;i++)for(int j=,tmp=;j<=b.n;j++){
tmp=(tmp+b.f[j-])%p;
g[i+j]=(g[i+j]+(long long)f[i]*tmp%p*C[i+j][j]%p*C[n+b.n-i-j-][b.n-j]%p)%p;
}
memcpy(f,g,sizeof(f));
n+=b.n;
return *this;
}
DP &operator*=(const DP &b){
static int g[maxn];
memset(g,,sizeof(g));
int sum=;
for(int j=;j<b.n;j++)sum=(sum+b.f[j])%p;
for(int i=;i<n;i++)for(int j=,tmp=sum;j<b.n;j++){
g[i+j]=(g[i+j]+(long long)f[i]*tmp%p*C[i+j][j]%p*C[n+b.n-i-j-][b.n-j]%p)%p;
tmp=(tmp-b.f[j]+p)%p;
}
memcpy(f,g,sizeof(f));
n+=b.n;
return *this;
}
}f[maxn];
void dfs(int);
vector<int>G[maxn];
vector<bool>W[maxn];
int T,n,prt[maxn];
int main(){
C[][]=;
for(int i=;i<=;i++)for(int j=;j<=i;j++){
C[i][j]=C[i-][j];
if(j)C[i][j]=(C[i][j]+C[i-][j-])%p;
}
scanf("%d",&T);
while(T--){
scanf("%d",&n);
memset(prt,,sizeof(prt));
for(int i=;i<=n;i++){
G[i].clear();
W[i].clear();
f[i].clear();
}
for(int i=,x,y;i<n;i++){
char c;
scanf("%d %c%d",&x,&c,&y);
x++;
y++;
G[x].push_back(y);
W[x].push_back(c=='>');
G[y].push_back(x);
W[y].push_back(c=='<');
}
dfs();
int ans=;
for(int i=;i<n;i++)ans=(ans+f[].f[i])%p;
printf("%d\n",ans);
}
return ;
}
void dfs(int x){
for(int i=;i<(int)G[x].size();i++)if(G[x][i]!=prt[x]){
prt[G[x][i]]=x;
dfs(G[x][i]);
if(W[x][i])f[x]+=f[G[x][i]];
else f[x]*=f[G[x][i]];
}
}
bzoj3167 [Heoi2013]Sao的更多相关文章
- [BZOJ3167][HEOI2013]SAO[树dp+组合数学]
题意 给定 \(n\) 个节点和 \(n-1\) 个限制,每个节点有一个权值,每个限制形如:\(a_i< a_j\) ,问有多少个 \(1\) 到 \(n\) 排列满足要求. \(n\leq 1 ...
- 【BZOJ3167】[HEOI2013]SAO(动态规划)
[BZOJ3167][HEOI2013]SAO(动态规划) 题面 BZOJ 洛谷 题解 显然限制条件是一个\(DAG\)(不考虑边的方向的话就是一棵树了). 那么考虑树型\(dp\),设\(f[i][ ...
- 【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}\) 优化的过程,基础转移方程推导可以参考其他巨佬的博 ...
随机推荐
- [小tips]使用vscode,根据vue模板文件生成代码
本着苍蝇虽小也是肉的精神...... 目标: 我们希望每次新建.vue文件后,VSCODE能够根据配置,自动生成我们想要的内容. 方法: 打开VSCODE编辑器,依次选择"文件 -> ...
- Python3模块: hashlib
简介: 用于加密相关的操作,代替了md5模块和sha模块,主要提供SHA1,SHA224,SHA256,SHA384,SHA512,MD5算法. 在python3中已经废弃了md5和sha模块,简单说 ...
- Machine learning 第8周编程作业 K-means and PCA
1.findClosestCentroids function idx = findClosestCentroids(X, centroids) %FINDCLOSESTCENTROIDS compu ...
- zookeeper知识点学习
单机模式配置: Zookeeper 的启动脚本在 bin 目录下,Linux 下的启动脚本是 zkServer.sh 在你执行启动脚本之前,还有几个基本的配置项需要配置一 下,Zookeeper 的配 ...
- (转)Python科学计算之Pandas详解,pythonpandas
https://www.cnblogs.com/linux-wangkun/p/5903380.html-------pandas 学习(1): pandas 数据结构之Series https:// ...
- (转)使用 DB2 HADR 选择用于灾难恢复的 SUPERASYNC 模式
使用 DB2 HADR 选择用于灾难恢复的 SUPERASYNC 模式 Vishnu G 和 Hemant Singh2013 年 6 月 25 日发布 WeiboGoogle+用电子邮件发送本页面 ...
- Vundle,Vim 的 Bundle(转)
长久以来,我管理 Vim 配置的方式都非常原始—— zip 打包,然后发到邮箱上.偶尔会发生忘记备份,或者配置混淆的状况,不过由于懒筋发作,竟然这个方案就这么用了两年. 终有一天,我觉得这个方法太笨了 ...
- matplotlib基本使用(矩形图、饼图、热力图、3D图)
使用matplotlib画简单的图形: #-*- coding:utf-8 -*- from numpy.random import randn import matplotlib.pyplot as ...
- Mysql 断电数据损毁恢复
error log: Database page corruption on disk or a failed 处理: /etc/my.cnf 设置 innodb_force_recovery = 6 ...
- 机器学习--boosting家族之XGBoost算法
一.概念 XGBoost全名叫(eXtreme Gradient Boosting)极端梯度提升,经常被用在一些比赛中,其效果显著.它是大规模并行boosted tree的工具,它是目前最快最好的开源 ...