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. 【UGUI】 (二)--------- 小地图

    在绝大多数游戏中,小地图都是极为常见的一个模块而且十分重要.在Unity里面如何制作一个地图其实也是比较简单的 一. 创建玩家与敌人 创建一个Capsule,命名为Player,代表我们的游戏玩家,创 ...

  2. Phaser3游戏三角学应用--一只跟随屏幕点击位置游动的鱼

    fish fish 资源图: fish-136x80.png undersea-bg.png 代码 var config = { type: Phaser.AUTO, parent: 'iFiero' ...

  3. 第三次ScrumMeeting博客

    第三次ScrumMeeting博客 本次会议于10月27日(五)22时整在3公寓725房间召开,持续10分钟. 与会人员:刘畅.方科栋.窦鑫泽.张安澜. 1. 每个人的工作(有Issue的内容和链接) ...

  4. CSS布局之圣杯布局和双飞翼布局

    其实圣杯布局和双飞翼布局实现的都是三栏布局,两边的盒子宽度固定,中间盒子自适应,也就是我们常说的固比固布局.它们实现的效果都是一样的,差别在于其实现的思想. 一.圣杯布局 html代码中,将重要的内容 ...

  5. ORM(object relational Maping)

    ORM即对象关系映射,是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术. 简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将java程序中的对象自动持久化到关系数据库中.本质上 ...

  6. c# 调用c++dll二次总结

    1.pinvoke结构不对称,添加语句(网上有) 2.含回调函数,成员参数的结构体必须完全,尽管自己用不到. 3.加深对c++指针的理解.一般情况下,类型加*等效于c++中的ref.但对于short* ...

  7. 安装cocoa pods

    1.移除现有Ruby默认源 $gem sources --remove https://rubygems.org/ 2.使用新的源 $gem sources -a https://ruby.taoba ...

  8. JScript脚本

    这个好强大啊 .fiddler2是部分是用这个语言开发的.

  9. java沙盒入门(2)

    Java在Internet上的应用已经日渐普遍,使用在网页上的Java程序称之为applet,利用Applet的嵌入能够使原本静态的HTML富有变化,并且能够做到"声"." ...

  10. QMdiArea及QMdiSubWindow实现父子窗口及布局方法

    版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:QMdiArea及QMdiSubWindow实现父子窗口及布局方法     本文地址:http ...