潜入行动

题意:

思路:

  1. 转移过程中的某些枚举部分可以优化掉。
  2. 方案数的统计是组合数学,累计乘积和。
  3. 统计方案时会爆int,但开 longlong 内存也炸,需要中途 ll 强转回 int。

Code:Code:Code:

#include<bits/stdc++.h>
#include<unordered_map>
#define debug cout << "debug---  "
#define debug_ cout << "\n---debug---\n"
#define oper(a) operator<(const a& ee)const
#define forr(a,b,c) for(int a=b;a<=c;a++)
#define mem(a,b) memset(a,b,sizeof a)
#define cinios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
#define all(a) a.begin(),a.end()
#define sz(a) (int)a.size()
#define endl "\n"
#define ul (u << 1)
#define ur (u << 1 | 1)
using namespace std;typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> PII;const int N = 1e5 + 10, M = 2e6 + 10, mod = 1e9 + 7;
int INF = 0x3f3f3f3f; ll LNF = 0x3f3f3f3f3f3f3f3f;
int n, m, B = 10, ki;int h[N], e[M], ne[M], idx;
void add(int a, int b) {e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
int siz[N];
int dp[N][102][2][2], tmp[102][2][2];
//表示以 x 为根的子树中共放了 k 个监听装置,其中 x 点放没放装置,x 点有没有被监听到的方案数//(如果 x 没放,在以 x 为根的子树中除 x 外的其它结点都要被监听到,不然肯定之后监听不到这些点)// 00:x 没放也没有被监听到,显然对于所有子节点都不能放但要被监听到,故 dp[j][k][0][1]
//
// 10:x 放了没被监听到,则子节点一定不放,有可能被监听到,故 dp[j][k][0][1] + dp[j][k][0][0]
//
// 01: x 没放有被监听到,则子节点都要被监听,部分 枚举 放 dp[j][k][1][1],其余的不放 dp[j][k][0][1],但可以发现枚举很是麻烦,时间复杂度也高。事实上我们可以分两种情况考虑,在遍历子树的中途就计算好:
//
//   1.x 没放有被监听到 dp[x][i][0][1],则接下来连接的子树放不放都行,但要满足被监听,即 dp[j][k][1][1] + dp[j][k][0][1]
//   2.x 没放也没被监听 dp[x][i][0][0],则接下来的子树需要放才行,即 dp[j][k][1][1]
//
// 11: x 放了也被监听了,则子节点有可能被监听到,也有可能没有,枚举放 dp[j][k][1][0] / dp[j][k][1][1] , 其余不放 dp[j][k][0][0] / dp[j][k][0][1]
// 同理优化枚举。。。
////longlong数组最多开到 3e7 左右,再大就超过 250mb 了,所以需要中途 ll 强转回 int
inline void ad(int& x, ll y) {x = (x + (y % mod)) % mod;
}void dfs(int x, int fa) {siz[x] = dp[x][0][0][0] = dp[x][1][1][0] = 1;for (int b = h[x]; ~b; b = ne[b]) {int v = e[b]; if (v == fa)continue;dfs(v, x);for (int k = 0; k <= ki; k++)for (int i = 0; i < 2; i++)for (int j = 0; j < 2; j++) {tmp[k][i][j] = dp[x][k][i][j];dp[x][k][i][j] = 0;}//把 i 、j 留出来当变量,别折磨自己眼睛for (int i = 0; i <= min(ki, siz[x]); i++)for (int j = 0; j <= min(ki - i, siz[v]); j++) {int& x1 = dp[x][i + j][0][0];ad(x1, 1ll * tmp[i][0][0] * dp[v][j][0][1]);int& x2 = dp[x][i + j][1][0];ad(x2, 1ll * tmp[i][1][0] * (dp[v][j][0][1] + dp[v][j][0][0]));int& x3 = dp[x][i + j][0][1];ad(x3, 1ll * tmp[i][0][0] * dp[v][j][1][1]);ad(x3, 1ll * tmp[i][0][1] * (dp[v][j][1][1] + dp[v][j][0][1]));int& x4 = dp[x][i + j][1][1];ad(x4, 1ll * tmp[i][1][0] * (dp[v][j][1][1] + dp[v][j][1][0]));ad(x4, 1ll * tmp[i][1][1] * (1ll * dp[v][j][0][0] + dp[v][j][0][1] + dp[v][j][1][0] + dp[v][j][1][1]));}siz[x] += siz[v];//善用siz,优化时间}
}void solve() {cin >> n >> ki;mem(h, -1);for (int i = 1; i < n; i++) {int a, b;cin >> a >> b;add(a, b), add(b, a);}dfs(1, -1);//根据定义int ans = (dp[1][ki][1][1] + dp[1][ki][0][1]) % mod;cout << ans;
}int main() {cinios;int T = 1;for (int t = 1; t <= T; t++) {solve();}return 0;
}
/*
*/

洛谷:P4516 [JSOI2018] 潜入行动(树形dp、树上分组背包统计方案数)相关推荐

  1. 洛谷P1351 联合权值(树形dp)

    题意 题目链接 Sol 一道很简单的树形dp,然而被我写的这么长 分别记录下距离为\(1/2\)的点数,权值和,最大值.以及相邻儿子之间的贡献. 树形dp一波.. #include<bits/s ...

  2. 洛谷2015 二叉苹果树 树形DP

    https://www.luogu.org/problemnew/show/P2015 二叉苹果树 时间限制: 1 Sec  内存限制: 128 MB 题目描述 有一棵苹果树,如果树枝有分叉,一定是分 ...

  3. hdu 5148 树形dp,分组背包

    题目: 题目分析: 状态方程: dp[当前节点的标号][当前已经选取的城市数] 设已经选取的城市数是K 初始状态: dp[u][0] = dp[u][1] = 0 , 其他的将值设置为无穷大 树形转移 ...

  4. 洛谷 2016 战略游戏(树形DP)

    题目描述 Bob喜欢玩电脑游戏,特别是战略游戏.但是他经常无法找到快速玩过游戏的办法.现在他有个问题. 他要建立一个古城堡,城堡中的路形成一棵树.他要在这棵树的结点上放置最少数目的士兵,使得这些士兵能 ...

  5. 洛谷P1122 最大子树和 树形DP初步

    小明对数学饱有兴趣,并且是个勤奋好学的学生,总是在课后留在教室向老师请教一些问题.一天他早晨骑车去上课,路上见到一个老伯正在修剪花花草草,顿时想到了一个有关修剪花卉的问题.于是当日课后,小明就向老师提 ...

  6. 洛谷P2016 战略游戏【树形dp】

    P2016 战略游戏 时间限制 1.00s 内存限制 125.00MB 题目描述 Bob喜欢玩电脑游戏,特别是战略游戏.但是他经常无法找到快速玩过游戏的办法.现在他有个问题. 他要建立一个古城堡,城堡 ...

  7. 洛谷 1351 联合权值——树形dp

    题目:https://www.luogu.org/problemnew/show/P1351 对拍了一下,才发现自己漏掉了那种拐弯的情况. #include<iostream> #incl ...

  8. 洛谷 1131 [ZJOI2007]时态同步——树形dp

    题目:https://www.luogu.org/problemnew/show/P1131 因为越高,调节一个影响到的越多,所以底下只要把子树间的差异消除了就行了,与其他部分的差异由更高的边调节. ...

  9. 洛谷P3047 附近的牛 树形dp

    给出一个 n ≤ 1 e 5 n\leq1e5 n≤1e5的树,每个点都有一个点权,求所有的点距离 k k k以内的所有的点的点权和. 不错的题.先简单想:如果是要求这个点向下所有距离 k k k以内 ...

最新文章

  1. mysql connector python linux_MySQL Connector/Python 安装、测试
  2. 关于iOS 11的适配
  3. Educational Codeforces Round 108(Rated for Div. 2) E - Off by One(一种一般图的边最大匹配,好题)
  4. 大数据时代的隐身模式下的大数据创业公司
  5. PDOStatement 类 FETCH_* 系列
  6. Qt中用QuaZip来压缩和解压缩文件
  7. python创建txt文件
  8. 【Java】实战Java虚拟机之五“开启JIT编译”
  9. 关于c# .net爬虫
  10. Apache-SimpleEmail 简单应用
  11. 判断mac地址单播还是组播(shell脚本)
  12. 基于JAVA+SpringMVC+Mybatis+MYSQL的博客系统
  13. expect实现配置机器信任关系
  14. Java-Set、Map
  15. 如何利用迅雷下载百度云?
  16. 什么是IP地址、IP协议?
  17. html转pdf手机,html转pdf
  18. Python下载和安装图文教程[超详细]
  19. Android TextView显示表情、标签、超链接
  20. Web前端_配合swiper滑动插件实现同比例双指缩放图片

热门文章

  1. 读懂 TS 中联合类型和交叉类型的含义
  2. 香港旅游攻略香港旅游购物指南
  3. 初学者不建议月python吗_为什么我不建议你将python作为入门编程语言
  4. MySql系列之mysql查询执行过程(附Mysql架构图及实操解析)
  5. SQL学习经验总结(第一期)共6期
  6. linux标准发音视频,Linux的标准发音
  7. [IOS笔记][Bugly]首次使用bugly收集app崩溃信息
  8. stagefright,OpenMax框架
  9. sql groud by 语句
  10. EasyRecovery15MacPro离线便捷扫描恢复数据