LINK


有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】的更多相关文章

  1. Codeforces Round #474-E(树形dp)

    一.题目链接 http://codeforces.com/contest/960/problem/B 二.题意 给定一棵$N$个节点的树,每个节点的权值$V$.定义树中两点$u_1$和$u_m$的权值 ...

  2. Choosing Capital for Treeland CodeForces - 219D (树形DP)

    传送门 The country Treeland consists of n cities, some pairs of them are connected with unidirectional  ...

  3. Codeforces 431C - k-Tree - [树形DP]

    题目链接:https://codeforces.com/problemset/problem/431/C 题意: 定义一个 $k$ 树,即所有节点都有 $k$ 个儿子节点,相应的这 $k$ 条边的权重 ...

  4. Codeforces 161D(树形dp)

    \(dp[v][k]\)代表以\(v\)的子树为起点,以点\(v\)为终点长度为\(k\)的方案有多少种. 转移只需将子树加和:计算\(ans\)由两部分组成,一是\(dp[v][k]\),另一部分是 ...

  5. Codeforces 709E. Centroids 树形DP

    题目链接:http://codeforces.com/contest/709/problem/E 题意: 给你一棵树,你可以任删一条边和加一条边,只要使得其仍然是一棵树,输出每个点是否都能成为重心 题 ...

  6. 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 ...

  7. Codeforces 743D:Chloe and pleasant prizes(树形DP)

    http://codeforces.com/problemset/problem/743/D 题意:求最大两个的不相交子树的点权和,如果没有两个不相交子树,那么输出Impossible. 思路:之前好 ...

  8. codeforces 161D Distance in Tree 树形dp

    题目链接: http://codeforces.com/contest/161/problem/D D. Distance in Tree time limit per test 3 secondsm ...

  9. codeforces 337D Book of Evil (树形dp)

    题目链接:http://codeforces.com/problemset/problem/337/D 参考博客:http://www.cnblogs.com/chanme/p/3265913 题目大 ...

  10. codeforces 212E IT Restaurants(树形dp+背包思想)

    题目链接:http://codeforces.com/problemset/problem/212/E 题目大意:给你一个无向树,现在用两种颜色去给这颗树上的节点染色.用(a,b)表示两种颜色分别染的 ...

随机推荐

  1. Flutter学习笔记(二)

    *.assets 当引用图片的时候,需要在pubspec.yaml的文件中的flutter下添加assets,类似于下面的样子: image.png 这里需要注意的是文件里的assets只要一个缩进即 ...

  2. 【Golang 接口自动化03】 解析接口返回XML

    上一篇我们学习了怎么发送各种数据类型的http请求,这一篇我们来介绍怎么来解析接口返回的XML的数据. 解析接口返回数据 定义结构体 假设我们现在有一个接口返回的数据resp如下: <?xml ...

  3. URAL 1029 Ministry

    URAL 1029 思路: dp+记录路径 状态:dp[i][j]表示到(i,j)这个位置为止的最少花费 初始状态:dp[1][i]=a[1][i](1<=i<=m) 状态转移:dp[i] ...

  4. C#中的?

    1. 可空类型修饰符(?):引用类型可以使用空引用表示一个不存在的值,而值类型通常不能表示为空.例如:string str=null; 是正确的,int i=null; 编译器就会报错.为了使值类型也 ...

  5. Win7 默认.lnk打开方式全是别的程序 还原的办法

    Xu言: no zuo no die~ 今天,一个朋友问我,他电脑桌面上点任何东西都是提示下载... - -||| 本以为是中毒了,然后上去看了一眼..发现他自己把所有.lnk 的默认打开方式选择了搜 ...

  6. 通过IIS寄宿WCF服务

    WCF全面解析一书中的例子S104,直接将Service目录部署到iis是无法得到服务相应的,需要在项目中新建一个web项目,删除掉自动生成的所有文件之后,把Service目录下的Calculator ...

  7. codeforces 559b//Equivalent Strings// Codeforces Round #313(Div. 1)

    题意:定义了字符串的相等,问两串是否相等. 卡了时间,空间,不能新建字符串,否则会卡. #pragma comment(linker,"/STACK:1024000000,102400000 ...

  8. python-day48--mysql之视图、触发器、事务、存储过程、函数

    一.视图(不推荐使用) 1).视图是一个虚拟表(非真实存在) 2).使用视图我们可以把查询过程中的临时表摘出来,用视图去实现,这样以后再想操作该临时表的数据时就无需重写复杂的sql了,直接去视图中查找 ...

  9. JQuery $未定义

    ---恢复内容开始--- JQuery $未定义 转载▼   jquery是Yii集成的,利用jquery写的代码$(document).ready(function(){// 操作列表$('.ope ...

  10. 简话Angular 08 Angular ajax

    一句话: 它们Angular框架声明周期的各个阶段,常规约定各专注于特定功能,经过处理也可以互相替换 1.功能细分简解 $http 类似JQuery ajax,支持promise $http.json ...