Codeforces gym101955 A【树形dp】
有n个大号和m个小号
然后需要对这些号进行匹配,一个大号最多匹配2个小号
匹配条件是大号和小号构成了前缀关系
字符串长度不超过10
问方案数
思路
因为要构成前缀关系
所以就考虑在trie树上dp
\(f_{i,j,k}\)表示i的子树中,还需要来自祖先的j个小号,并且有需要匹配但是没有匹配的小号k个
然后如果当前是一个大号节点
可以从子树中选一个小号
\(f_{u,j,k - 1}<=f_{v,j,k} * k\)
可以从子树中选两个小号
\(f_{u,j,k - 2}<=f_{v,j,k} * (\frac{k *(k - 1)}{2})\)
可以从祖先中选一个小号
\(f_{u,j+1, k}<=f_{u,j,k}\)
可以从祖先中选两个小号(因为在祖先中需要选择两次,避免重复计算这里除以2)
\(f_{u,j+2,k}<=f_{u,j,k}*\frac{1}{2}\)
可以从祖先选一个子树选一个
\(f_{u,j+1,k-1}<=f_{u,j,k}*k\)
这里我们考虑等价选择的多种方案的时候只在深度浅的地方算
然后实际上如果是小号节点,同理就好了
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
const int Mod = 1e9 + 7;
const int CHARSET_SIZE = 26;
int add(int a, int b) {
return (a += b) >= Mod ? a - Mod : a;
}
int mul(int a, int b) {
return 1ll * a * b % Mod;
}
struct Node {
int ch[CHARSET_SIZE], typ;
void init() {
typ = 0;
memset(ch, 0, sizeof(ch));
}
} p[N];
int tot = 0, n, m;
char c[N];
int f[N][12][22], g[N][12][22];
void init() {
tot = 1;
p[1].init();
}
void insert(char *s, int typ) {
int len = strlen(s + 1), u = 1;
for (int i = 1; i <= len; i++) {
int cur = s[i] - 'a';
if (!p[u].ch[cur])
p[p[u].ch[cur] = ++tot].init();
u = p[u].ch[cur];
}
p[u].typ = typ;
}
void dfs(int u) {
for (int i = 0; i <= 10; i++)
for (int j = 0; j <= 20; j++)
f[u][i][j] = g[u][i][j] = 0;
f[u][0][0] = 1;
for (int i = 0; i < CHARSET_SIZE; i++) {
int v = p[u].ch[i];
if (!v) continue;
dfs(v);
for (int j = 10; j >= 0; j--)
for (int k = 20; k >= 0; k--) if (f[u][j][k])
for (int l = 0; l <= 10 - j; l++)
for (int t = 0; t <= 20 - k; t++)
g[u][j + l][k + t] = add(g[u][j + l][k + t], mul(f[u][j][k], f[v][l][t]));
for (int j = 0; j <= 10; j++)
for (int k = 0; k <= 20; k++) {
f[u][j][k] = g[u][j][k];
g[u][j][k] = 0;
}
}
if (!p[u].typ) return;
for (int i = 0; i <= 10; i++) {
for (int j = 0; j <= 20; j++) if (f[u][i][j]) {
if (p[u].typ == 1) {
if (i + 1 <= 10)
g[u][i + 1][j] = add(g[u][i + 1][j], f[u][i][j]);
if (j - 1 >= 0)
g[u][i][j - 1] = add(g[u][i][j - 1], mul(j, f[u][i][j]));
if (i + 2 <= 10)
g[u][i + 2][j] = add(g[u][i + 2][j], mul((Mod + 1) >> 1, f[u][i][j]));
if (j - 2 >= 0)
g[u][i][j - 2] = add(g[u][i][j - 2], mul((j * (j - 1)) >> 1, f[u][i][j]));
if (i + 1 <= 10 && j - 1 >= 0)
g[u][i + 1][j - 1] = add(g[u][i + 1][j - 1], mul(j, f[u][i][j]));
} else {
if (i - 1 >= 0)
g[u][i - 1][j] = add(g[u][i - 1][j], mul(i, f[u][i][j]));
if (j + 1 <= 20)
g[u][i][j + 1] = add(g[u][i][j + 1], f[u][i][j]);
}
}
}
for (int i = 0; i <= 10; i++)
for (int j = 0; j <= 20; j++)
f[u][i][j] = add(f[u][i][j], g[u][i][j]);
}
void solve(int cas) {
init();
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++) {
scanf("%s", c + 1);
insert(c, 1);
}
for (int i = 1; i <= m; i++) {
scanf("%s", c + 1);
insert(c, 2);
}
dfs(1);
printf("Case #%d: %d\n", cas, f[1][0][0]);
}
int main() {
int T; scanf("%d", &T);
for (int i = 1; i <= T; i++)
solve(i);
return 0;
}
Codeforces gym101955 A【树形dp】的更多相关文章
- Codeforces Round #474-E(树形dp)
一.题目链接 http://codeforces.com/contest/960/problem/B 二.题意 给定一棵$N$个节点的树,每个节点的权值$V$.定义树中两点$u_1$和$u_m$的权值 ...
- Choosing Capital for Treeland CodeForces - 219D (树形DP)
传送门 The country Treeland consists of n cities, some pairs of them are connected with unidirectional ...
- Codeforces 431C - k-Tree - [树形DP]
题目链接:https://codeforces.com/problemset/problem/431/C 题意: 定义一个 $k$ 树,即所有节点都有 $k$ 个儿子节点,相应的这 $k$ 条边的权重 ...
- Codeforces 161D(树形dp)
\(dp[v][k]\)代表以\(v\)的子树为起点,以点\(v\)为终点长度为\(k\)的方案有多少种. 转移只需将子树加和:计算\(ans\)由两部分组成,一是\(dp[v][k]\),另一部分是 ...
- Codeforces 709E. Centroids 树形DP
题目链接:http://codeforces.com/contest/709/problem/E 题意: 给你一棵树,你可以任删一条边和加一条边,只要使得其仍然是一棵树,输出每个点是否都能成为重心 题 ...
- Codeforces Round #384 (Div. 2)D - Chloe and pleasant prizes 树形dp
D - Chloe and pleasant prizes 链接 http://codeforces.com/contest/743/problem/D 题面 Generous sponsors of ...
- Codeforces 743D:Chloe and pleasant prizes(树形DP)
http://codeforces.com/problemset/problem/743/D 题意:求最大两个的不相交子树的点权和,如果没有两个不相交子树,那么输出Impossible. 思路:之前好 ...
- codeforces 161D Distance in Tree 树形dp
题目链接: http://codeforces.com/contest/161/problem/D D. Distance in Tree time limit per test 3 secondsm ...
- codeforces 337D Book of Evil (树形dp)
题目链接:http://codeforces.com/problemset/problem/337/D 参考博客:http://www.cnblogs.com/chanme/p/3265913 题目大 ...
- codeforces 212E IT Restaurants(树形dp+背包思想)
题目链接:http://codeforces.com/problemset/problem/212/E 题目大意:给你一个无向树,现在用两种颜色去给这颗树上的节点染色.用(a,b)表示两种颜色分别染的 ...
随机推荐
- 怎么运行cocos2dx 3.x simulator?
1.simulator的好处是: 快速切换分辨率:F5快速重新启动项目: 这对于脚本语言来说都是很方便快捷的. 2.涉及到显示参数的文件有两个: ①lang,这个是菜单的语言文件,如果没有这个文件的话 ...
- 算法笔记--KMP算法 && EXKMP算法
1.KMP算法 这个博客写的不错:http://www.cnblogs.com/SYCstudio/p/7194315.html 模板: next数组的求解,那个循环本质就是如果相同前后缀不能加上该位 ...
- C#中的约束类型
- GetContent
Sub GetContent(ByVal URL As String, ByVal SheetName As String) Dim strText As String Dim i As Long D ...
- homestead 添加新站点
homestead 添加站点的时候遇到了坑,这里记录下来,也顺便给大家一个参考. 1. 首先修改homestead.yaml文件(虽然你有可能不知道这个文件在哪,但是我也不会帮你找的.) 2. 接着修 ...
- Jenkins安装以及邮件配置
Jenkins介绍 Jenkins是一个java开发的.开源的.非常好用持续集成的工具,它能帮我们实现自动化部署环境.测试.打包等等的工作,还可以在构建任务成功或者失败之后给我们发邮件通知. 什么叫持 ...
- YOLO v2 损失函数源码分析
损失函数的定义是在region_layer.c文件中,关于region层使用的参数在cfg文件的最后一个section中定义. 首先来看一看region_layer 都定义了那些属性值: layer ...
- Hive之 Python写UDF
大自然的搬运工: 参考: 使用Python编写Hive UDF https://www.iteblog.com/archives/2329.html 使用 Python 编写 Hive UDF 环境问 ...
- UVA-10061 How many zero's and how many digits ? (数论)
题目大意:让求n!在base进制下的位数以及末尾0的连续个数. 题目分析:一个m位的b进制数N,最小是b^(m-1),最大不超过b^m,即b^(m-1)≤N<b^m.解不等式,得log10(N) ...
- Leetcode 89
回溯写到自闭:不想就删了: class Solution { public: vector<int> grayCode(int n) { vector<vector<int&g ...