Description

给你一个树,可以染 \(m\) 个颜色,定义一个特殊颜色 \(k\) , 要求保证整棵树上特殊颜色的个数不超过 \(x\) 个。同时,如果一个节点是特殊颜色,那么它的相邻节点的颜色编号必须全部小于 \(k\)。求方案数。

Input

第一行 \(n,m\) 代表节点个数和颜色树

下面 \(n~-~1\) 行描述一棵树

最后一行是特殊颜色 \(k\) 和颜色个数 \(x\)

Output

输出一行一个整数,代表答案对 \(10^9~+~7\) 取模结果

Hint

\(Forall:\)

\(n~\leq~10^5~,~m~\leq~10^9~,~k~\leq~m~,~x~\leq~10\)

Solution

这题感觉有点像DDOSvoid的疑惑

我 爆 破 我 自 己

数数题,考虑DP。

显然这个题的选点分为三种,分别是小于 \(k\),等于 \(k\),大于 \(k\)。同时有颜色个数的限制,于是可以设 \(f_{i,j,0/1/2}\) 代表以 \(i\) 为根的子树,选了 \(j\) 个特殊颜色,其中节点 \(i\) 的颜色 小于/等于/大于 \(k\)

考虑一个节点只有两个儿子的情况,直接把贡献乘一下即可。

考虑一个节点有多个儿子的时候,每加入一个新节点产生的贡献如何计算:

设 \(g_{i,j,0/1/2}\) 为 \(u\) 的子树(省略第一维),考虑前 \(i\) 个儿子,选了 \(j\) 个 \(k\),节点 \(i\) 的状态是 \(0/1/2\) 的方案数。

一下假设当前枚举的是 \(u\) 的第 \(i\) 个儿子。

考虑 \(u\) 选小于 \(k\) 的情况:

则该儿子可以选 \(0/1/2\) 三种情况,这三种情况相互并行,应该将贡献相加,同时两两子树间互不影响,应将贡献相乘。

于是有

\[g_{i,j,0}~=~\sum_{h=0}^{j}(g_{i-1,j-h,0}~\times~\sum_{s=0}^{2}f_{to,h,s})
\]

同理,\(u\) 选等于 \(k\) 的情况:

该儿子只能选 \(0\) 一种情况,于是有

\[g_{i,j,1}~=~\sum_{h=0}^{j}(g_{i-1,j-h,1}~\times~f_{to,h,0})
\]

同理,\(u\) 选大于 \(k\) 的情况:

该儿子可以选 \(0/2\) 两种可能,于是

\[g_{i,j,2}~=~\sum_{h=0}^{j}(g_{i-1,j-h,2}~\times~\sum_{s=0,2}f_{to,h,s})
\]

设 \(u\) 有 \(v\) 个孩子,于是

\[f_{u,j,0/1/2}~=~g_{v,j,0/1/2}
\]

当然 \(g\) 可以把第一维滚掉,这样就没有空间问题辣~

于是就可以统计答案了。记得取模。代码里面因为不知道哪里爆掉了于是干脆 \(define~~int~~ll\) 了23333

Code

#include <cstdio>
#include <cstring>
#ifdef ONLINE_JUDGE
#define freopen(a, b, c)
#endif
#define rg register
#define ci const int
#define cl const long long
#define int ll typedef long long ll; namespace IPT {
const int L = 1000000;
char buf[L], *front=buf, *end=buf;
char GetChar() {
if (front == end) {
end = buf + fread(front = buf, 1, L, stdin);
if (front == end) return -1;
}
return *(front++);
}
} template <typename T>
inline void qr(T &x) {
rg char ch = IPT::GetChar(), lst = ' ';
while ((ch > '9') || (ch < '0')) lst = ch, ch=IPT::GetChar();
while ((ch >= '0') && (ch <= '9')) x = (x << 1) + (x << 3) + (ch ^ 48), ch = IPT::GetChar();
if (lst == '-') x = -x;
} template <typename T>
inline void ReadDb(T &x) {
rg char ch = IPT::GetChar(), lst = ' ';
while ((ch > '9') || (ch < '0')) lst = ch, ch = IPT::GetChar();
while ((ch >= '0') && (ch <= '9')) x = x * 10 + (ch ^ 48), ch = IPT::GetChar();
if (ch == '.') {
ch = IPT::GetChar();
double base = 1;
while ((ch >= '0') && (ch <= '9')) x += (ch ^ 48) * ((base *= 0.1)), ch = IPT::GetChar();
}
if (lst == '-') x = -x;
} namespace OPT {
char buf[120];
} template <typename T>
inline void qw(T x, const char aft, const bool pt) {
if (x < 0) {x = -x, putchar('-');}
rg int top=0;
do {OPT::buf[++top] = x % 10 + '0';} while (x /= 10);
while (top) putchar(OPT::buf[top--]);
if (pt) putchar(aft);
} const int maxn = 100010;
const int maxm = 200010;
const int MOD = 1000000007; struct Edge {
int to, nxt;
};
Edge edge[maxm]; int hd[maxn], ecnt = 1;
inline void cont(ci from, ci to) {
Edge &e = edge[++ecnt];
e.to = to; e.nxt = hd[from]; hd[from] = ecnt;
} int n, m, x, v, dv;
int frog[maxn][15][3], gorf[maxn][2][15][3]; void reading();
void dfs(ci, ci); signed main() {
freopen("1.in", "r", stdin);
qr(n); qr(m);
reading();
qr(v); qr(x); dv = m - v;
dfs(1, 0);
int ans = 0;
for (rg int i = 0; i <= x; ++i)
for(rg int j = 0; j < 3; ++j) ans = (ans + frog[1][i][j]) % MOD;
qw(ans, '\n', true);
return 0;
} void reading() {
int a, b;
for (rg int i = 1; i < n; ++i) {
a = b = 0;
qr(a); qr(b);
cont(a, b);
cont(b, a);
}
} void dfs(ci u, ci pree) {
int pre = 0;
gorf[u][pre][0][0] = v - 1;
gorf[u][pre][1][1] = 1;
gorf[u][pre][0][2] = dv;
for (int i = hd[u]; i; i = edge[i].nxt) if(i != pree) {
int &to = edge[i].to;
dfs(to, i ^ 1);
pre ^= 1;
memset(gorf[u][pre], 0, sizeof gorf[u][pre]);
for (rg int j = 0; j <= x; ++j) {
for (rg int k = 0; k <= j; ++k) {
gorf[u][pre][j][0] = (gorf[u][pre][j][0] + 1ll * gorf[u][pre ^ 1][j - k][0] * (frog[to][k][0] + frog[to][k][1] + frog[to][k][2])) % MOD;
gorf[u][pre][j][1] = (1ll * gorf[u][pre ^ 1][j - k][1] * frog[to][k][0] + gorf[u][pre][j][1]) % MOD;
gorf[u][pre][j][2] = (1ll * gorf[u][pre ^ 1][j - k][2] * (frog[to][k][0] + frog[to][k][2]) + gorf[u][pre][j][2]) % MOD;
}
}
}
for (rg int i = 0; i <= x; ++i)
for (rg int j = 0; j < 3; ++j)
frog[u][i][j] = gorf[u][pre][i][j];
#ifdef DEBUG
printf("EM%d:\n", u);
for (rg int i = 0; i <= x; ++i) {
for (rg int j = 0; j < 3; ++j)
printf("%d %d %d\n",i, j, frog[u][i][j]);
}
#endif
}

Summary

这类树上求方案数的问题都需要在转移时借助一个辅助数组,记录已经枚举过得儿子的信息,然后计算当前这个儿子加入的贡献。

【DP】【CF855C】 Helga Hufflepuff's Cup的更多相关文章

  1. C. Helga Hufflepuff's Cup 树形dp 难

    C. Helga Hufflepuff's Cup 这个题目我感觉挺难的,想了好久也写了很久,还是没有写出来. dp[i][j][k] 代表以 i 为根的子树中共选择了 j 个特殊颜色,且当前节点 i ...

  2. Codeforces 855C - Helga Hufflepuff's Cup

    855C - Helga Hufflepuff's Cup 题意 要求构建一棵树,树上至多可以存在 \(x\) 个权值为 \(k\) 的重要点,且与重要点连边的点的权值必须小于 \(k\),问有多少种 ...

  3. Helga Hufflepuff's Cup CodeForces - 855C

    Helga Hufflepuff's Cup CodeForces - 855C 题意:给一棵n个节点的树,要给每一个节点一个附加值,附加值可以为1-m中的一个整数.要求只能有最多x个节点有附加值k. ...

  4. T2980 LR棋盘【Dp+空间/时间优化】

    Online Judge:未知 Label:Dp+滚动+前缀和优化 题目描述 有一个长度为1*n的棋盘,有一些棋子在上面,标记为L和R. 每次操作可以把标记为L的棋子,向左移动一格,把标记为R的棋子, ...

  5. 【codeforces Manthan, Codefest 17 C】Helga Hufflepuff's Cup

    [链接]h在这里写链接 [题意]     k是最高级别的分数,最高界别的分数最多只能有x个.     1<=k<=m;     和k相邻的点的分数只能小于k;     n个点的树,问你每个 ...

  6. 【10.3校内测试【国庆七天乐!】】【DP+组合数学/容斥】【spfa多起点多终点+二进制分类】

    最开始想的暴力DP是把天数作为一个维度所以怎么都没有办法优化,矩阵快速幂也是$O(n^3)$会爆炸. 但是没有想到另一个转移方程:定义$f[i][j]$表示每天都有值的$i$天,共消费出总值$j$的方 ...

  7. 【DP+树状数组】BZOJ1264-[AHOI2006]基因匹配Match

    [题目大意] 给定n个数和两个长度为n*5的序列,两个序列中的数均有1..n组成,且1..n中每个数恰好出现5次,求两个序列的LCS. [思路] 预处理每个数字在a[i]中出现的五个位置.f[i]示以 ...

  8. BZOJ1079 [SCOI2008]着色方案 【dp记忆化搜索】

    题目 有n个木块排成一行,从左到右依次编号为1~n.你有k种颜色的油漆,其中第i种颜色的油漆足够涂ci个木块. 所有油漆刚好足够涂满所有木块,即c1+c2+-+ck=n.相邻两个木块涂相同色显得很难看 ...

  9. 【DP|多重背包可行性】POJ-1014 Dividing

    Dividing Time Limit: 1000MS Memory Limit: 10000K Description Marsha and Bill own a collection of mar ...

随机推荐

  1. C#入门经典第十章例题 - - 卡牌

    1.库 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ...

  2. 解决Sublime Text 3中文显示乱码(tab中文方块)问题

    博客分类:  Sublime   一.文本出现中文乱码问题 1.打开Sublime Text 3,按Ctrl+-打开控制行,复制粘贴以下python代码,然后回车运行. 2. 复制并粘贴如下代码: P ...

  3. TW实习日记:第七天

    今天早上,将项目的两个企业微信接口:登录和应用消息发送接口,做了最后的收尾工作,把目前我能解决的问题算是基本都解决了.早上还开了一个会,大意是组长封装了许多组件叫我们使用,在不断的使用中打磨组件的可用 ...

  4. C++数字三角形问题与dp算法

    题目:数字三角形 题目介绍:如图所示的数字三角形,要求从最上方顶点开始一步一步下到最底层,每一步必须下一层,求出所经过的数字的最大和. 输入:第一行值n,代表n行数值:后面的n行数据代表每一行的数字. ...

  5. 日本IT行业劳动力缺口达22万 在日中国留学生迎来就业好时机 2017/07/18 11:25:09

    作者:倪亚敏 来源:日本新华侨报 发布时间:2017/07/18 11:25:09     据日本政府提供的数据,日本2018年应届毕业生的“求人倍率”已经达到了1.78倍.换言之,就是100名大学生 ...

  6. [leetcode-914-X of a Kind in a Deck of Cards]

    In a deck of cards, each card has an integer written on it. Return true if and only if you can choos ...

  7. Cross origin requests are only supported for protocol schemes: http, data, chrome,chrome-extension的问题

    Cross origin requests are only supported for protocol schemes: http, data, chrome,chrome-extension的问 ...

  8. 常用的os操作方法

    os.sep可以取代操作系统特定的路径分隔符.windows下为 “”os.name字符串指示你正在使用的平台.比如对于Windows,它是'nt',而对于Linux/Unix用户,它是'posix' ...

  9. LCA(Tarjan算法)模板

    一.查询一组的LCA Nearest Common Ancestors A rooted tree is a well-known data structure in computer science ...

  10. Yogurt factory

    Description The cows have purchased a yogurt factory that makes world-famous Yucky Yogurt. Over the ...