4013: [HNOI2015]实验比较

链接

分析:

  首先把等号用并查集合并起来。

  由于只存在最多一个质量不比i差的数,发现这是森林。若x<y,连边x->y。于是建虚拟根节点0。

  然后树形dp,f[i][j]表示第i棵子树内,分成了j段的方案数,即存在j-1个小于号。

  依次合并每个子树,假设一棵树内是a段,一棵树内是b段,合并后变成k段,$k \in [max(a,b), a + b]$

  $f[i][k]=f[u][a] \times f[v][b] \times C_{k}^{a} \times C_{a}^{b-(k-a)}$

  后面一项的意义:此时相当于有k个盒子,有a个白球,b个黑球,每个盒子里不能同时出现两个黑球或者白球。那么先让每个白球选一个盒子放进去,黑球先补上空着的,最后多出的黑球放到以前白球的盒子里。

  复杂度:复杂度的话,看似O(N^4),但是,每个点对只会在其LCA处被枚举到并产生O(N)的运算量 精细地实现的话复杂度是O(N^3)的。by CRZbulabula 

代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<iostream>
#include<cctype>
#include<set>
#include<map>
#include<queue>
#include<vector>
using namespace std;
typedef long long LL; inline int read() {
int x=,f=;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-;
for(;isdigit(ch);ch=getchar())x=x*+ch-'';return x*f;
}
inline int Read() {
char ch = getchar();for(;ch!='<'&&ch!='='&&ch!='>'; ch=getchar());
return (ch == '<' ? : (ch == '=' ? : ));
} const int N = , mod = 1e9 + ;
struct Edge { int to, nxt; } e[];
int head[N], C[N][N], fa[N], ext[N][N], vis[N], deg[N], q[N], siz[N], f[N][N], tmp[N], En;
vector<int> vec[N]; inline void add_edge(int u,int v) {
++En; e[En].to = v, e[En].nxt = head[u]; head[u] = En; deg[v] ++;
}
int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]); }
inline void add(int &x,int y) { x += y; if (x >= mod) x -= mod; }
inline int mul(int x,int y) { return 1ll * x * y % mod; }
void dfs(int u) {
siz[u] = f[u][] = ;
for (int I = head[u]; I; I = e[I].nxt) {
int v = e[I].to;
dfs(v);
for (int i = ; i < siz[u]; ++i)
for (int j = ; j <= siz[v]; ++j)
for (int k = max(i, j); k <= i + j; ++k) {
int A = mul(f[u][i + ], f[v][j]), B = mul(C[k][i], C[i][j - k + i]);
add(tmp[k + ], mul(A, B));
}
siz[u] += siz[v];
for (int i = ; i <= siz[u]; ++i) f[u][i] = tmp[i], tmp[i] = ;
}
}
int main () {
int n = read(), m = read();
C[][] = ;
for (int i = ; i <= n; ++i) {
C[i][] = ;
for (int j = ; j <= i; ++j)
C[i][j] = (C[i - ][j] + C[i - ][j - ]) % mod;
}
for (int i = ; i <= n; ++i) fa[i] = i;
for (int i = ; i <= m; ++i) {
int x = read(), ty = Read(), y = read();
if (!ty) {
x = find(x), y = find(y);
if (x != y) fa[x] = y;
}
else if (ty == ) vec[x].push_back(y);
else vec[y].push_back(x);
}
for (int i = ; i <= n; ++i) {
int x = find(i);
for (int sz = vec[i].size(), j = ; j < sz; ++j) {
int y = find(vec[i][j]);
if (!ext[x][y]) add_edge(x, y), ext[x][y] = ;
}
}
for (int i = ; i <= n; ++i)
if (deg[i] == && fa[i] == i) add_edge(, i);
int L = , R = ;
q[++R] = ;
while (L <= R) {
int u = q[L ++]; vis[u] = ;
for (int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to;
if (!(--deg[v])) q[++R] = v;
}
}
for (int i = ; i <= n; ++i)
if (fa[i] == i && !vis[i]) { cout << ; return ; }
dfs();
int ans = ;
for (int i = ; i <= siz[]; ++i) add(ans, f[][i]);
cout << ans;
return ;
}

4013: [HNOI2015]实验比较的更多相关文章

  1. bzoj 4013: [HNOI2015]实验比较

    Description 小D 被邀请到实验室,做一个跟图片质量评价相关的主观实验.实验用到的图片集一共有 N 张图片,编号为 1 到 N.实验分若干轮进行,在每轮实验中,小 D会被要求观看某两张随机选 ...

  2. 【BZOJ】4013: [HNOI2015]实验比较

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4013 中第i 条涉及的图片对为(KXi, Xi),判断要么是KXi < Xi ,要么 ...

  3. [BZOJ4013][HNOI2015]实验比较(树形DP)

    4013: [HNOI2015]实验比较 Time Limit: 5 Sec  Memory Limit: 512 MBSubmit: 756  Solved: 394[Submit][Status] ...

  4. 【BZOJ4013】[HNOI2015]实验比较(动态规划)

    [BZOJ4013][HNOI2015]实验比较(动态规划) 题面 BZOJ 洛谷 题解 看题目意思就是给你一棵树,连边表示强制顺序关系.然后你要给点染色,在满足顺序关系的情况下,将序列染成若干个颜色 ...

  5. BZOJ 4013/Luogu P3240 [HNOI2015] 实验比较 (树形DP)

    题目传送门 分析 放一个dalao博客: xyz32768 的博客,看完再回来看本蒟蒻的口胡吧(其实嘛-不回来也行) 精髓是合并的方案数的计算,至于为什么是Ci−1j−1\large C_{i-1}^ ...

  6. [HNOI2015]实验比较

    Description 小D 被邀请到实验室,做一个跟图片质量评价相关的主观实验.实验用到的图片集一共有 N 张图片,编号为 1 到 N.实验分若干轮进行,在每轮实验中,小 D会被要求观看某两张随机选 ...

  7. 【bzoj4013】 HNOI2015—实验比较

    http://www.lydsy.com/JudgeOnline/problem.php?id=4013 (题目链接) 题意 给出$n$个数的$m$个大小关系,问它们之间可以形成的单调不降的序列有多少 ...

  8. P3240 [HNOI2015]实验比较 树形DP

    \(\color{#0066ff}{ 题目描述 }\) 小D 被邀请到实验室,做一个跟图片质量评价相关的主观实验.实验用到的图片集一共有 \(N\) 张图片,编号为 \(1\) 到\(N\).实验分若 ...

  9. BZOJ4013 : [HNOI2015]实验比较

    首先用并查集将等号缩点,然后拓扑排序判断有没有环,有环则无解,否则通过增加超级源点$0$,可以得到一棵树. 设$f[x][y]$表示$x$子树里有$y$种不同的数字的方案数,由底向上DP. 对于当前点 ...

随机推荐

  1. iOS设计模式 - 组合

    iOS设计模式 - 组合 原理图 说明 将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性.掌握组合模式的重点是要理解清楚 “部分/整体” 还有 ...

  2. 远程计算机 进程/服务 启动停止(WMI)

    WMI的远程管理需要其计算机的本地管理员组权限,例:gwmi win32_computersystem -computer win08r2d #在远程计算机上启动 notepad.exe 进程invo ...

  3. September 17th 2017 Week 38th Sunday

    Distance could make you forget about them, but the memories would always be there. 距离会让你遗忘,但是回忆却始终在那 ...

  4. Django 错误之 No module named ‘MySQLdb’

    由于卸载Mysql时将很多相关依赖包都卸载了,重装mysql后启动django出现如下错误: django.core.exceptions.ImproperlyConfigured:Error loa ...

  5. gamit安装

    需要准备的文件: 默认已安装好虚拟机和Ubuntu系统 1.输入用户名密码,进入Ubuntu10.04桌面.按下“Ctrl+Alt+T”,进入终端: 2.在终端输入“sudo gedit /etc/a ...

  6. Promise & Deferred Objects in JavaScript Pt.2: in Practice

    原文:http://blog.mediumequalsmessage.com/promise-deferred-objects-in-javascript-pt2-practical-use Intr ...

  7. python多进程(三)

    消息队列 消息队列”是在消息的传输过程中保存消息的容器. 消息队列最经典的用法就是消费者和生成者之间通过消息管道来传递消息,消费者和生成者是不通的进程.生产者往管道中写消息,消费者从管道中读消息.   ...

  8. objc_msgSend函数的实现

    毕竟汇编语言代码比较晦涩难懂,因此这里将函数的实现反汇编成C语言的伪代码: //下面的结构体中只列出objc_msgSend函数内部访问用到的那些数据结构和成员. /* 其实SEL类型就是一个字符串指 ...

  9. java基础面试题(JVM篇)

    1.什么是Java虚拟机?为什么Java被称作是“平台无关的编程语言”? Java 虚拟机是一个可以执行 Java 字节码的虚拟机进程.Java 源文件被编译成能被 Java 虚拟机执行的字节码文件. ...

  10. Java实现Package编译和访问

    Java实现Package编译和访问 说明 所有文件都是使用UTF-8编码来写的,请不要用Windows记事本随便打开 Test.java文件中注释的方法说明了该类是不能访问其方法的 文件目录树 bi ...