[HEOI 2013]SAO
Description
给你一个 \(n\) 个节点的有向树,问你这棵树的拓扑序个数,对大质数取模。多测,测试组数 \(T\)。
\(1\leq n\leq 1000, 1\leq T\leq 5\)
Solution
以 1 为根。记 \(f_{u,i}\) 表示 \(u\) 为根的子树中 \(u\) 的拓扑序号为 \(i\) 时的方案数。
从儿子 \(v\) 向父亲 \(u\) 转移时,考虑 \((u,v)\) 的方向。以 \(u\rightarrow v\) 为例。
枚举 \(u\) 的拓扑序号 \(i\),\(v\) 的拓扑序 \(j\)。那么 \(u,v\) 的分别的原排列如图示(\(A,B\) 为原先在 \(u\) 前/后的部分,\(C,D\) 同理),
\[
\begin{aligned}
\underline{\quad A\quad}&\quad i\quad\underline{\quad B\quad}\\
&\ \ \ \downarrow\\
\underline{\quad C\quad}&\quad j\quad\underline{\quad D\quad}
\end{aligned}
\]
我们考虑 \(u\) 在新序列中的位置 \(k\),可以得到
\[
\text{new}f_{u,k} = \sum_{i,j}{k-1\choose i-1}{sz_u+sz_v-k\choose sz_u-i}f_{u,i}f_{v,j}
\]
其中 \(sz_u\) 表示子树 \(u\) 的大小。
容易发现 \(j\) 这一维可以前缀和优化。
故最终复杂度为 \(O(n^2)\)。
Code
#include <bits/stdc++.h>
using namespace std;
const int yzh = 1000000007, N = 1000+5;
int f[N][N], sz[N], t, n, u, v, g[N], fac[N], ifac[N];
struct tt {
int to, nxt, c;//0->
} edge[N<<1];
int path[N], top;
char sign;
int C(int n, int m) {return 1ll*fac[n]*ifac[m]%yzh*ifac[n-m]%yzh; }
void dfs(int u, int fa) {
f[u][1] = sz[u] = 1;
for (int v, i = path[u]; i; i = edge[i].nxt)
if ((v = edge[i].to) != fa) {
dfs(v, u);
memcpy(g, f[u], sizeof(g));
memset(f[u], 0, sizeof(g));
if (edge[i].c == 0) {
for (int i = 1; i <= sz[u]; i++)
for (int k = i; k <= i+sz[v]-1; k++)
(f[u][k] += 1ll*C(k-1, i-1)*C(sz[u]+sz[v]-k, sz[u]-i)%yzh*g[i]%yzh*(f[v][sz[v]]-f[v][k-i])%yzh) %= yzh;
} else {
for (int i = 1; i <= sz[u]; i++)
for (int k = i+1; k <= i+sz[v]; k++)
(f[u][k] += 1ll*C(k-1, i-1)*C(sz[u]+sz[v]-k, sz[u]-i)%yzh*g[i]%yzh*f[v][k-i]%yzh) %= yzh;
}
sz[u] += sz[v];
}
for (int i = 1; i <= n; i++) (f[u][i] += f[u][i-1]) %= yzh;
}
void add(int u, int v, int c) {
edge[++top] = (tt){v, path[u], c};
path[u] = top;
}
int main() {
n = 1000;
ifac[0] = ifac[1] = fac[0] = 1;
for (int i = 2; i <= n; i++) ifac[i] = -1ll*yzh/i*ifac[yzh%i]%yzh;
for (int i = 1; i <= n; i++)
ifac[i] = 1ll*ifac[i]*ifac[i-1]%yzh,
fac[i] = 1ll*i*fac[i-1]%yzh;
scanf("%d", &t);
while (t--) {
scanf("%d", &n); top = 0;
for (int i = 1; i <= n; i++) {
path[i] = sz[i] = 0;
for (int j = 1; j <= n; j++) f[i][j] = 0;
}
for (int i = 1; i < n; i++) {
scanf("%d %c %d", &u, &sign, &v); ++u, ++v;
if (sign == '<') 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]+yzh)%yzh);
}
return 0;
}
[HEOI 2013]SAO的更多相关文章
- [BZOJ 3167][HEOI 2013]SAO
[BZOJ 3167][HEOI 2013]SAO 题意 对一个长度为 \(n\) 的排列作出 \(n-1\) 种限制, 每种限制形如 "\(x\) 在 \(y\) 之前" 或 & ...
- 解题:HEOI 2013 SAO
题面 不好讲,直接上式子吧=.= 设$dp[i][j]$表示考虑完$i$的子树后$i$的排名为$j$的方案数,然后转移类似树形背包,具体来说是(这里假设子树在$i$后选,其实反过来还用这个式子答案也是 ...
- [HEOI 2013 day2] SAO (树形动态规划)
题目大意 给一棵N个节点的有向树(N <= 1000),求其拓扑序列个数. 思路 我们将任意一个点作为根,用dp[i][j]表示以节点i为根的子树满足节点i在第j个位置上的拓扑序列的个数.在求节 ...
- 【BZOJ 3165】【HEOI 2013】Segment
往区间上覆盖一次函数,做法是用线段树维护标记永久化. 每次都忘了线段树要4倍空间,第一次交总是RE,再这么手残的话考场上就真的要犯逗了. #include<cstdio> #include ...
- [HEOI 2013 day2] 钙铁锌硒维生素 (线性代数,二分图匹配)
题目大意 给定两个n阶方阵,方阵B的行i能匹配方阵A的行j当且仅当在第一个方阵中用行向量i替换行向量j后,第一个方阵满秩,显然这是个二分图匹配问题,问是否存在完美匹配,如果存在,还要输出字典序最小的方 ...
- 【BZOJ 3166】【HEOI 2013】Alo
http://www.lydsy.com/JudgeOnline/problem.php?id=3166 这道题难点在于求能对一个次大值有贡献的区间. 设这个次大值为\(a_i\),\(a_i\)左边 ...
- [总结]一些 DP 优化方法
目录 注意本文未完结 写在前面 矩阵快速幂优化 前缀和优化 two-pointer 优化 决策单调性对一类 1D/1D DP 的优化 \(w(i,j)\) 只含 \(i\) 和 \(j\) 的项--单 ...
- 2013 Asia Changsha Regional Contest---Josephina and RPG(DP)
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=4800 Problem Description A role-playing game (RPG and ...
- SharePoint 2013: A feature with ID has already been installed in this farm
使用Visual Studio 2013创建一个可视web 部件,当右击项目选择"部署"时报错: "Error occurred in deployment step ' ...
随机推荐
- source insight 编译后出现停止工作解决方法
解决方法: 工程的路径不要有中文,都用英文
- 一些封装的php函数
swoole群中奥总共享的创建文件夹: function make_dir($folder){ $reval = false; if (!file_exists($folder)){ /* 如果目录不 ...
- 推荐算法之---FM算法;
一,FM算法: 1,逻辑回归上面进行了交叉特征.算法复杂度优化从O(n^3)->O(k*n^2)->O(k*n). 2,本质:每个特征都有一个k维的向量,代表的是每个特征都有k个不可告人的 ...
- P1030 求先序排列 (一个非常棒的写法)
理论正确就是真正的正确,误... 就是找嘛,找到每一个对应字符,然后对应的左右子树的区间,然后就可以了. #include <bits/stdc++.h> using namespace ...
- 介绍Mobility Group
Mobility或Roaming是无线客户端能够安全地从一个AP无缝关联到另一个AP的能力,并且延迟尽可能的短. 当无线客户端和AP关联并通过AP进行身份验证时,注册AP的WLC会将客户端条目放在自己 ...
- Servlet线程安全问题(转载)
转载地址:https://www.cnblogs.com/LipeiNet/p/5699944.html 前言:前面说了很多关于Servlet的一些基础知识,这一篇主要说一下关于Servlet的线程安 ...
- about Base64
用webservice传送文件的时候发现,如果发送的文件中有0x00字符,会被认为是字符串结尾,后面的内容就发送不过去,因此需要对不是纯文本格式的文件做BASE64编码,这样文件中就不会有0x00这样 ...
- java 编译java文件 以及生成可执行jar
1.新建java project: 2.src下新建包以及class文件: 3.打包: 5.选取目标mainclass 很关键决定jar是否可执行: 7.build jar : 8:artifact ...
- springboot学习4使用日志:logback
springboot学习4使用日志:logback 一.基本知识说明 SpringBoot默认使用logback作为日志框架 ,所以引入起步依赖后就可以直接使用logback,不需要其他依赖. Spr ...
- Vulnhub_DC7 记录
基本步骤 经验 & 总结 对信息还是不敏感,其实也是因为对Drupal这个CMS并不熟悉,不知道哪些地方是默认的那些地方是作者修改,比如这个"DC7USER". 对Drup ...