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)表示两种颜色分别染的 ...
随机推荐
- JQuery 自己主动触发事件
经常使用模拟 有时候,须要通过模拟用户操作,来达到单击的效果.比如在用户进入页面后,就触发click事件,而不须要用户去主动单击. 在JQuery中.能够使用trigger()方法完毕模拟操作.比如能 ...
- threejs和3d各种效果的学习
写给即将开始threejs学习的自己,各种尝试,各种记忆.不要怕,灰色的年华终会过去. 一个技术学习的快慢,以及你的深刻程度,还有你的以后遇到这个东西的时候的反应速度,很大程度上,取决于你的博客的深刻 ...
- C#对GZIP压缩和解压
/// <summary> /// 将Gzip的byte数组读取为字符串 /// </summary> /// <param name="bytes" ...
- 各个安卓版本 使用的 Linux Kernel Version
Android Version |API Level |Linux Kernel in AOSP --------------------------------------------------- ...
- 使用mothur进行OTU聚类
微生物16S的OTU聚类工具有很多,最常用的就是 usearch.cdhit-OTU.mothur. 这些工具大多都是针对二代测序平台的,usearch的64bit版本是收费的. 如果要跑PacBio ...
- php数组转化为字符串
1.函数explode(); 这个是字符串转化为数组 , implode() ;这个是数组转化为字符串. $array=explode(separator,$string); $string=imp ...
- DIV字体
1.如何设定文字字体.颜色.大小 —— 使用font font-style设定斜体,比如font-style: italicfont-weight设定文字粗细,比如font-weight: bold; ...
- 算法笔记——C/C++语言基础篇(已完结)
开始系统学习算法,希望自己能够坚持下去,期间会把常用到的算法写进此博客,便于以后复习,同时希望能够给初学者提供一定的帮助,手敲难免存在错误,欢迎评论指正,共同学习.博客也可能会引用别人写的代码,如有引 ...
- 使用SAE(VAE)检测信用卡欺诈——感觉误报率还是比较高啊 70%+误报 蛋疼
from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScale ...
- RabbitMQ整合spring
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...