BZOJ 4013 实验比较
Description
小D被邀请到实验室,做一个跟图片质量评价相关的主观实验。实验用到的图片集一共有\(N\)张图片,编号为\(1\)到\(N\)。实验分若干轮进行,在每轮实验中,小\(D\)会被要求观看某两张随机选取的图片,然后小\(D\)需要根据他自己主观上的判断确定这两张图片谁好谁坏,或者这两张图片质量差不多。用符号“\(<\)”、“\(>\)”和“\(=\)”表示图片\(x\)和\(y\)(\(x,y\)为图片编号)之间的比较:如果上下文中\(x\)和\(y\)是图片编号,则\(x < y\)表示图片\(x\)“质量优于”\(y\),\(x > y\)表示图片\(x\)“质量差于”\(y\),\(x = y\)表示图片\(x\)和\(y\)“质量相同”;也就是说,这种上下文中,“\(<\)”、“\(>\)”、“\(=\)”分别是质量优于、质量差于、质量相同的意思;在其他上下文中,这三个符号分别是小于、大于、等于的含义。图片质量比较的推理规则(在\(x\)和\(y\)是图片编号的上下文中):(1)\(x < y\)等价于\(y > x\)。(2)若\(x < y\)且\(y = z\),则\(x < z\)。(3)若\(x < y\)且\(x = z\),则\(z < y\)。(4)\(x=y\)等价于\(y=x\)。(5)若\(x=y\)且\(y=z\),则\(x=z\)。 实验中,小 D 需要对一些图片对\((x,y)\),给出\(x < y\) 或\(x = y\)或\(x > y\)的主观判断。小\(D\)在做完实验后, 忽然对这个基于局部比较的实验的一些全局性质产生了兴趣。在主观实验数据给定的情形下,定义这\(N\)张图片的一个合法质量序列为形如“\(x_{1}\;R_{1}\;x_{2}\;R_{2}\;x_{3}\;R_{3} \cdots x_{N-1}\;R_{N-1}\;x_{N}\)”的串,也可看作是集合\(\lbrace x_{i}\;R_{i}\;x_{i+1} \mid 1 \le i \le N-1 \rbrace\),其中\(x_{i}\)为图片编号,\(x_{1},x_{2},\cdots,x_{N}\)两两互不相同(即不存在重复编号),\(R_{i}\)为<或=,“合法”是指这个图片质量序列与任何一对主观实验给出的判断不冲突。 由于实验已经做完一段时间了,小D已经忘了一部分主观实验的数据。对每张图片\(i\),小 D 都{最多只记住了某一张质量不比\(i\)差的另一张图片\(K_{i}\)。这些小\(D\)仍然记得的质量判断一共有\(M\)条\((0 \le M \le N)\),其中第\(i\)条涉及的图片对为\((K_{X_{i}}, X_{i})\),判断要么是\(K_{X_{i}} < X_{i}\),要么是\(K_{X_{i}}=X_{i}\),而且所有的\(X_{i}\)互不相同。小D打算就以这\(M\)条自己还记得的质量判断作为他的所有主观数据。现在,基于这些主观数据,我们希望你帮小D求出这 \(N\)张图片一共有多少个不同的合法质量序列。我们规定:如果质量序列中出现“\(x=y\)”,那么序列中交换\(x\)和\(y\)的位置后仍是同一个序列。因此: \(1<2=3=4<5\)和\(1<4=2=3<5\)是同一个序列,\(1 < 2 = 3\)和\(1 < 3 = 2\)是同一个序列,而\(1 < 2 < 3\)与\(1 < 2 = 3\)是不同的序列,\(1<2<3\)和\(2<1<3\)是不同的序列。由于合法的图片质量序列可能很多, 所以你需要输出答案对\(10^{9}+7\)取模的结果。
Input
第一行两个正整数\(N,M\),分别代表图片总数和小D仍然记得的判断的条数;
接下来\(M\)行,每行一条判断,每条判断形如“\(x < y\)”或者”\(x = y\)”。
Output
输出仅一行,包含一个正整数,表示合法质量序列的数目对\(10^{9}+7\)取模的结果。
Sample Input
5 4
1 < 2
1 < 3
2 < 4
1 = 5
Sample Output
5
Hint
\(N \le 100\)
将\(=\)缩掉之后如果该图没有环,那么一定是一棵森林结构,我们增添超级根,就变成了一颗树的结构了。
如果\(A,B\)可以用\(=\)关系的话,那么\(A,B\)一定没有子树关系。所以,我们可以想到状态\(f_{i,j}\)表示以\(i\)为根的子树,有\(j\)段(\(j-1\)个\(<\)的方案数)。利用辅助数组进行转移\(g_{i,j,k}\)表示\(i\)的前\(j\)个儿子,分成了\(k\)段的方案数。那么我们就有转移$$g_{i,j,z} = \sum C_{z}^{x} C_{x}^{x+y-z} g_{i,j-1,x} \times f_{son,y}(max(x,y) \le z \le x+y)$$
其中\(C_{z}^{x} C_{x}^{x+y-z}\)是转移系数,表示有\(x\)个白球,\(y\)个黑球,放进\(z\)个槽中,每个位置不能有两个颜色一样的球的方案数。
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<queue>
using namespace std;
typedef long long ll;
#define rhl (1000000007)
#define maxn (110)
int father[maxn],side[maxn],next[maxn],toit[maxn],g[2][maxn][maxn];
int tot,num,cnt,ind[maxn],C[maxn][maxn],f[maxn][maxn],ans,N,M;
bool exist[maxn];
struct node { int a,b; }edge[maxn];
inline int find(int a) { if (father[a] != a) father[a] = find(father[a]); return father[a]; }
inline void add(int a,int b)
{
next[++cnt] = side[a]; side[a] = cnt;
toit[cnt] = b; ++ind[b]; exist[a] = exist[b] = true;
}
inline bool topsort()
{
queue <int> team;
for (int i = 1;i <= N;++i) if (exist[i]&&!ind[i]) team.push(i),add(0,i);
int ret = 0;
while (!team.empty())
{
++ret; int now = team.front(); team.pop();
for (int i = side[now];i;i = next[i])
if (!--ind[toit[i]]) team.push(toit[i]);
}
return ret == num;
}
inline int dp(int now)
{
int sz = 0,tmp,cur = 1;
g[0][now][0] = 1;
for (int i = side[now],v;i;i = next[i],cur ^= 1)
{
tmp = dp(v = toit[i]);
for (int x = 0;x <= sz;++x)
for (int y = 1;y <= tmp;++y)
for (int z = max(x,y);z <= x+y;++z)
{
g[cur][now][z] += (ll)g[cur^1][now][x]*f[v][y]%rhl*(ll)C[z][x]%rhl*(ll)C[x][x+y-z]%rhl;
if (g[cur][now][z] >= rhl) g[cur][now][z] -= rhl;
}
memset(g[cur^1][now],0,sizeof(g[cur^1][now]));
sz += tmp;
}
for (int i = 0;i <= sz;++i) f[now][i+1] = g[cur^1][now][i];
return sz+1;
}
int main()
{
freopen("4013.in","r",stdin);
freopen("4013.out","w",stdout);
scanf("%d %d",&N,&M); num = N;
for (int i = 1;i <= N;++i) father[i] = i;
for (int i = 1,a,b;i <= M;++i)
{
char c;
scanf("%d %c %d\n",&a,&c,&b);
if (c == '<') edge[++tot] = (node){a,b};
else
{
int r1 = find(a),r2 = find(b);
if (r1 != r2) father[r1] = r2,--num;
}
}
for (int i = 1;i <= tot;++i) add(find(edge[i].a),find(edge[i].b));
if (!topsort()) printf("0");
else
{
C[0][0] = 1;
for (int i = 1;i <= N;++i)
{
C[i][0] = 1;
for (int j = 1;j <= i;++j)
{
C[i][j] = C[i-1][j] + C[i-1][j-1];
if (C[i][j] >= rhl) C[i][j] -= rhl;
}
}
int sz = dp(0);
for (int i = 1;i <= sz;++i) { ans += f[0][i]; if (ans >= rhl) ans -= rhl; }
printf("%d",ans);
}
fclose(stdin); fclose(stdout);
return 0;
}
BZOJ 4013 实验比较的更多相关文章
- bzoj 4013: [HNOI2015]实验比较
Description 小D 被邀请到实验室,做一个跟图片质量评价相关的主观实验.实验用到的图片集一共有 N 张图片,编号为 1 到 N.实验分若干轮进行,在每轮实验中,小 D会被要求观看某两张随机选 ...
- BZOJ 4013 【HNOI2015】 实验比较
题目链接:实验比较 如果我们把相等关系全部缩起来的话,这道题给出的小于关系如果有环,那么就是不合法的,否则就构成了一片森林. 定义等于号连起来的所有变量看做一个块. 然后我们就可以令\(f_{i,j} ...
- BZOJ 4013/Luogu P3240 [HNOI2015] 实验比较 (树形DP)
题目传送门 分析 放一个dalao博客: xyz32768 的博客,看完再回来看本蒟蒻的口胡吧(其实嘛-不回来也行) 精髓是合并的方案数的计算,至于为什么是Ci−1j−1\large C_{i-1}^ ...
- 【BZOJ】4013: [HNOI2015]实验比较
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4013 中第i 条涉及的图片对为(KXi, Xi),判断要么是KXi < Xi ,要么 ...
- 4013: [HNOI2015]实验比较
4013: [HNOI2015]实验比较 链接 分析: 首先把等号用并查集合并起来. 由于只存在最多一个质量不比i差的数,发现这是森林.若x<y,连边x->y.于是建虚拟根节点0. 然后树 ...
- 【BZOJ】【3280】小R的烦恼
网络流/费用流 和软件开发那题基本相同,只是多加了一个“雇佣研究生”的限制:不同价格的研究生有不同的数量…… 那么只需加一个附加源点,对每一种研究生连边 S->ss 容量为l[i],费用为p[i ...
- BZOJ 3786 星系探索
Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅有一个依赖星球.主星球 ...
- bzoj 4824: [Cqoi2017]老C的键盘
Description 老 C 是个程序员. 作为一个优秀的程序员,老 C 拥有一个别具一格的键盘,据说这样可以大幅提升写程序的速度,还能让写出来的程序 在某种神奇力量的驱使之下跑得非常快.小 ...
- 【BZOJ4013】[HNOI2015]实验比较(动态规划)
[BZOJ4013][HNOI2015]实验比较(动态规划) 题面 BZOJ 洛谷 题解 看题目意思就是给你一棵树,连边表示强制顺序关系.然后你要给点染色,在满足顺序关系的情况下,将序列染成若干个颜色 ...
随机推荐
- Servlet 工作原理解析--转载
原文:http://www.ibm.com/developerworks/cn/java/j-lo-servlet/index.html?ca=drs- Web 技术成为当今主流的互联网 Web 应用 ...
- MSDN无法显示该页的解决办法
今天打开msdn,发现 查阅api时候 出现 “无法显示该页的解决办法“ 这个问题.解决方案如下: 在“运行”中输入regsvr32 "C:\Program Files\Common Fil ...
- fsdfasfsa
http://www.cnblogs.com/daniel206/archive/2008/01/16/1041729.html using System.IO;using System.Net;us ...
- PHP中的strtotime()对于31日求上个月有问题
原文出处 <?php $date = "2012-07-31"; $date_unix = strtotime($date); $lastmonth = strtotime( ...
- 【原创教程】JavaScript详解之语法和对象
JavaScript的好的想法:函数.弱类型.动态对象和一个富有表现力的对象字面量表示法. JavaScript的坏的想法:基于全局变量的编程模型. 好了,不管他是好的还是坏的,都是我的最爱,下面 ...
- JS1-属性操作
属性操作语法 读操作:获取.找到 元素.属性名 写操作:“添加”.替换.修改 元素.属性名 = 新的值 元素.innerHTML => 读取元素里面所有的html代码 元素.innerHTML ...
- CI框架篇之预热篇(1)
CodeIgniter 的基本都了解了,现在就开始预热,如果学习一门语言一样,我们最开始都是输出一个'HELLO WORLD'一样, 现在我们也通过输出这样一个内容,来了解基本的使用. CodeIgn ...
- [Mime] MimeHeaders--MimeHeader帮助类 (转载)
点击下载 MimeHeaders.rar 这个类是关于Mime的Headers类看下面代码吧 /// <summary> /// 类说明:Assistant /// 编 码 人:苏飞 // ...
- java 反射 - 获取成员变量的值.
通过反射,可以获取所有声明的成员变量(包括所有的),代码如下: package spt.test.src; public class Person { private String name = &q ...
- ca-bundle.crt to java truststore(e.g. trustStore.jks)
1. download java keyutilhttps://java-keyutil.googlecode.com/files/keyutil-0.4.0.jar 2. run the follo ...