【LOJ】#2117. 「HNOI2015」实验比较
题解
把所有=的点连起来,一个图合法肯定它是一个有向树森林
我们新建一个点,把这个点和其他所有树的树根连起来
定义\(dp[u][j]\)表示第u个点长度为j的序列的方案数
转移方法是
\(dp[u][j] += g[k] \cdot dp[v][h] \cdot \binom{j}{k} \cdot \binom{k}{h - j + k}\)
\(g[k]\)是我们记录之前儿子合并的序列为k的方案数
就是我们确定目标序列的长度为\(j\)后,选\(k\)个位置放第一个序列,在这\(k\)个位置中再选\(h - j + k\)个作为第二个序列和第一个序列重合的部分,和之前的空位一起放第二个序列
代码
#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define MAXN 105
//#define ivorysi
using namespace std;
typedef long long int64;
typedef long double db;
typedef unsigned int u32;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {putchar('-');x = -x;}
if(x >= 10) out(x / 10);
putchar('0' + x % 10);
}
const int MOD = 1000000007;
int N,M,id[MAXN],cnt;
int u[MAXN],v[MAXN],f[MAXN],ind[MAXN];
char ch[MAXN][5];
int vis[MAXN],C[MAXN][MAXN],dp[MAXN][MAXN],siz[MAXN],g[MAXN],s[MAXN];
struct node {
int next,to;
}E[MAXN * 2];
int sumE,head[MAXN];
int inc(int a,int b) {
return a + b >= MOD ? a + b - MOD : a + b;
}
int mul(int a,int b) {
return 1LL * a * b % MOD;
}
void add(int u,int v) {
E[++sumE].next = head[u];
E[sumE].to = v;
head[u] = sumE;
}
int getf(int u) {
return f[u] == u ? u : f[u] = getf(f[u]);
}
bool check(int u) {
vis[u] = 1;
for(int i = head[u] ; i ; i = E[i].next) {
int v = E[i].to;
if(!vis[v]) {if(!check(v)) return false;}
if(vis[v] == 1) return false;
}
vis[u] = 2;
return true;
}
void Init() {
read(N);read(M);
for(int i = 1 ; i <= N ; ++i) f[i] = i;
for(int i = 1 ; i <= M ; ++i) {
read(u[i]);scanf("%s",ch[i]);read(v[i]);
if(ch[i][0] == '=') {
f[getf(u[i])] = getf(v[i]);
}
}
for(int i = 1 ; i <= N ; ++i) {
if(!id[getf(i)]) id[getf(i)] = ++cnt;
}
for(int i = 1 ; i <= M ; ++i) {
if(ch[i][0] == '<') {
add(id[getf(u[i])],id[getf(v[i])]);
ind[id[getf(v[i])]]++;
}
}
N = cnt + 1;
for(int i = 1 ; i <= cnt ; ++i) if(!ind[i]) add(N,i);
C[0][0] = 1;
for(int i = 1 ; i <= 101 ; ++i) {
C[i][0] = 1;
for(int j = 1 ; j <= i ; ++j) {
C[i][j] = inc(C[i - 1][j],C[i - 1][j - 1]);
}
}
}
void dfs(int u) {
for(int i = head[u] ; i ; i = E[i].next) {
int v = E[i].to;
dfs(v);
}
memset(g,0,sizeof(g));
g[0] = 1;
for(int i = head[u] ; i ; i = E[i].next) {
int v = E[i].to;
for(int j = 0 ; j <= siz[u] + siz[v] ; ++j) {
s[j] = 0;
for(int k = 0 ; k <= siz[v] ; ++k) {
if(k > j) break;
for(int h = 0 ; h <= siz[u] ; ++h) {
if(h > j) break;
s[j] = inc(s[j],mul(mul(dp[v][k],g[h]),mul(C[j][k],C[k][h - j + k])));
}
}
}
for(int j = 0 ; j <= siz[u] + siz[v] ; ++j) g[j] = s[j];
siz[u] += siz[v];
}
++siz[u];
for(int j = 1 ; j <= siz[u] ; ++j) dp[u][j] = g[j - 1];
}
void Solve() {
for(int i = 1 ; i <= N ; ++i) {
if(!vis[i] && !check(i)) {puts("0");return;}
}
dfs(N);
int ans = 0;
for(int i = 0 ; i <= N ; ++i) ans = inc(ans,dp[N][i]);
out(ans);enter;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Init();
Solve();
return 0;
}
【LOJ】#2117. 「HNOI2015」实验比较的更多相关文章
- loj #2116. 「HNOI2015」开店
#2116. 「HNOI2015」开店 题目描述 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的想法当然非 ...
- Loj #2192. 「SHOI2014」概率充电器
Loj #2192. 「SHOI2014」概率充电器 题目描述 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品--概率充电器: 「采用全新纳米级加工技术,实现元件与导线能否通电完 ...
- Loj #3096. 「SNOI2019」数论
Loj #3096. 「SNOI2019」数论 题目描述 给出正整数 \(P, Q, T\),大小为 \(n\) 的整数集 \(A\) 和大小为 \(m\) 的整数集 \(B\),请你求出: \[ \ ...
- Loj #3093. 「BJOI2019」光线
Loj #3093. 「BJOI2019」光线 题目描述 当一束光打到一层玻璃上时,有一定比例的光会穿过这层玻璃,一定比例的光会被反射回去,剩下的光被玻璃吸收. 设对于任意 \(x\),有 \(x\t ...
- Loj #3089. 「BJOI2019」奥术神杖
Loj #3089. 「BJOI2019」奥术神杖 题目描述 Bezorath 大陆抵抗地灾军团入侵的战争进入了僵持的阶段,世世代代生活在 Bezorath 这片大陆的精灵们开始寻找远古时代诸神遗留的 ...
- Loj #2542. 「PKUWC2018」随机游走
Loj #2542. 「PKUWC2018」随机游走 题目描述 给定一棵 \(n\) 个结点的树,你从点 \(x\) 出发,每次等概率随机选择一条与所在点相邻的边走过去. 有 \(Q\) 次询问,每次 ...
- Loj #3059. 「HNOI2019」序列
Loj #3059. 「HNOI2019」序列 给定一个长度为 \(n\) 的序列 \(A_1, \ldots , A_n\),以及 \(m\) 个操作,每个操作将一个 \(A_i\) 修改为 \(k ...
- Loj #3056. 「HNOI2019」多边形
Loj #3056. 「HNOI2019」多边形 小 R 与小 W 在玩游戏. 他们有一个边数为 \(n\) 的凸多边形,其顶点沿逆时针方向标号依次为 \(1,2,3, \ldots , n\).最开 ...
- LOJ #2135. 「ZJOI2015」幻想乡战略游戏(点分树)
题意 给你一颗 \(n\) 个点的树,每个点的度数不超过 \(20\) ,有 \(q\) 次修改点权的操作. 需要动态维护带权重心,也就是找到一个点 \(v\) 使得 \(\displaystyle ...
随机推荐
- 在PE32位下安装64位2003、2008系统
步骤 1.进PE(这里是老毛桃为例) 2.将系统(这里windows2008 r2 为例)拷到本地硬盘 3.将ios镜像出来 4.在PE桌面找到 “windows系统安装”,浏览 系统文件 \sou ...
- CXF wsdl2java 生成java代码供客户端使用
CXF wsdl2java 生成java代码供客户端使用 环境配置:1.下载apache-cxf-2.6.2在环境变量中配置CXF_HOME 值为E:\gavin\cxf\apache-cxf-3.0 ...
- 新.Net架构必备工具列表
N多年前微软官网曾发了.Net下必备的十种工具,N多年过去了,世异时移,很多东西都已经变化了,那个列表也似乎陈旧了.而且,该文也只是对十种工具独立的介绍,显得有些罗列的感觉,是不是每个工具都是同等重要 ...
- plsql免安装客户端的配置
不安装oracle,在安装了plsql之后,需要连接数据库,连接数据库需要在tns中tnsnames.ora中配置 首先需要两个文件: network instantclient-basic-win3 ...
- 记录下(同一个计算机)多个容器 dockr bridge(桥接) docker-compose 配置
直接上 version: '3' services: mysql: container_name: mysql image: mysql:5.7.21 environment: MYSQL_ROOT_ ...
- 10.29训练赛第一场B题
题目大意:有n个队伍之间比赛,每两个队伍之间都有一场比赛,因此一共有n(n-1) / 2场比赛,但是这里丢失了一场比赛的记录,现在让你通过n(n-1) /2 -1场仍然存在的比赛记录来判断丢失的那条比 ...
- 【C++】wchar、char格式化符输出
VC.BCB.MinGW Linux下的GCC.C99标准 printf wprintf printf wprintf s char wchar_t char S wchar_t char * hs ...
- yum安装失败:ublic key for **.rpm is not installed
yum install mysql-server --nogpgcheck package_need_to_install
- MySQL 5.6.10 跨平台GTID复制实践
根据业务需要,建立MySQL复制来实现数据冗余. 1:binlog_format 默认值是:statement 有效值: ROW,基于行的复制 STATEMENT 基于语句级别的复制 MASTER ...
- Linux 定时器应用【转】
Linux 定时器应用 实验目的 阅读 Linux 相关源代码,学习 Linux 系统中的时钟和定时器原理,即,ITIMER_REAL实时计数,ITIMER_VIRTUAL 统计进程在用户模式执行的时 ...