Description

给定一棵以 1 为根的有根树,定义树的一个毒瘤集为一个集合,并且集合中任意两个元素之间不存在祖先与后代关系。

定义一个毒瘤集的毒瘤指数为集合内所有元素的价值之和

要求给定树的所有毒瘤集的毒瘤指数之和,答案对 100000007 取模。

但这个问题太难了,所以我们考虑化简。

因为点的编号跟它毒瘤指数密切相关,所以我们将会再给出一个整数 T,T = 1 表示 i 号点的毒瘤指数为 i,T = 0,表示所有点的毒瘤指数都是 1

Input

第一行两个整数 n、T,表示这棵树有 n 个节点。

接下来 n -1 行,每行两个整数 x 和 y,表示有一条边,连接 x 和 y。

Output

输出一个整数,表示答案。

Hint

\(Forall:\)

\(0~\leq~n~\leq~10^6~,~T~\leq~1\)

Solution

数数题,考虑DP。

设\(f_u\)是以\(u\)为根的子树,先考虑 \(T~=~0\) 的情况

当点\(u\)只有两个儿子 \(v_1~,~v_2\) 的时候,显然 \(f_u~=~f_{v_1}~+~f_{v_2}~+~f_{v_1}~\times~f_{v_2}~+~1\)

考虑\(u\)有多个儿子的时候也类似,设 \(g_j\) 为考虑点 \(u\) 的前\(j\)个子树的集合数,于是

\(g_j~=~g_{j-1}~\times~f_v~+~g_j~+~f_v\)

考虑 \(T~\neq~0\) 的情况

设 \(f_u\) 为以 \(u\) 为根的ans,\(g_u\) 为以 \(u\) 为根的集合个数

\[f_u~=~f_v~\times~g_u~+~f_u~\times~g_v~+~f_u~+f_v
\]

\[g_u~=~g_u~+~g_v~+~g_u~\times~g_v
\]

复杂度 \(O(n)\) 。听说有人用nlogn水过去了?

Code

#include <cstdio>
#ifdef ONLINE_JUDGE
#define freopen(a, b, c)
#endif
#define rg register
#define ci const int
#define cl const long long typedef long long int 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 = 1000010;
const int maxm = 2000010;
const int MOD = 100000007; 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, t;
int MU[maxn], frog[maxn], gorf[maxn]; void reading();
void dfs(ci, ci); int main() {
freopen("1.in", "r", stdin);
qr(n); qr(t);
if (t) {
for (rg int i = 1; i <= n; ++i) MU[i] = i;
} else {
for (rg int i = 1; i <= n; ++i) MU[i] = 1;
}
reading();
dfs(1, 0); qw(frog[1], '\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) {
for (int i = hd[u]; i; i = edge[i].nxt) if (i != pree) {
int &to = edge[i].to;
dfs(to, i ^ 1);
frog[u] = (1ll * frog[to] * gorf[u] % MOD + 1ll * frog[u] * gorf[to] % MOD + frog[to] + frog[u]) % MOD;
gorf[u] = (1ll * gorf[u] * gorf[to] % MOD + gorf[to] + gorf[u]) % MOD;
}
frog[u] = (frog[u] + MU[u]) % MOD;
gorf[u] = (gorf[u] + 1) % MOD;
}

Summary

这是一类非常经典的求树上方案数的题目,一般这类题目的解决方法是使用另一个数组表示“当前已经枚举到的”某些值,每枚举一个儿子单独计算贡献。

【DP】【P5007】 DDOSvoid 的疑惑的更多相关文章

  1. luogu5007 DDOSvoid 的疑惑 (树形dp)

    我们来算每个点出现在的集合的个数 设f[i]为i出现的集合个数,g[i]是只选子树i 可以有多少种选法 那就有$g[i]=1+\prod\limits_{j是i的孩子}{g[j]} , f[i]=f[ ...

  2. 【DP】【CF855C】 Helga Hufflepuff's Cup

    Description 给你一个树,可以染 \(m\) 个颜色,定义一个特殊颜色 \(k\) , 要求保证整棵树上特殊颜色的个数不超过 \(x\) 个.同时,如果一个节点是特殊颜色,那么它的相邻节点的 ...

  3. zzulioj--1719--小胖的疑惑(整数划分+dp打表)

    1719: 小胖的疑惑 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 108  Solved: 51 SubmitStatusWeb Board De ...

  4. 【CSP模拟】小凯的疑惑(DP)

    首先,这道题正解的思路是从subtask2而得来的,所以先讲一下subtask2的做法. 因为保证答案不超过long long,所以直接求最大权独立集即可:dp[u][0]表示u点一定不能取的答案,d ...

  5. dp和px,那些不得不吐槽的故事——Android平台图

    http://blog.sina.com.cn/s/blog_6499f8f101014ipq.html 一个优秀的手机软件,不仅要有精巧的功能,流畅的速度,让人赏心悦目的UI也往往是用户选择的重要理 ...

  6. 洛谷P1021邮票面值设计 [noip1999] dp+搜索

    正解:dfs+dp 解题报告: 传送门! 第一眼以为小凯的疑惑 ummm说实话没看标签我还真没想到正解:D 本来以为这么多年前的noip应该不会很难:D 看来还是太菜了鸭QAQ 然后听说题解都可以被6 ...

  7. 洛谷 P1140 相似基因(DP)

    传送门 https://www.cnblogs.com/violet-acmer/p/9852294.html 参考资料: [1]:https://www.cnblogs.com/real-l/p/9 ...

  8. dp和px,那些不得不吐槽的故事——Android平台图片文字元素单位浅析 (转)

    一个优秀的手机软件,不仅要有精巧的功能,流畅的速度,让人赏心悦目的UI也往往是用户选择的重要理由.作为移动产品的PM,也需要了解一些在UI设计中的基本知识. 1. px和pt,一对好伙伴 在视觉设计中 ...

  9. HDU-6156 Palindrome Function(数位DP)

    一.题目 二.思路 1.这是很明显的数位DP: 2.和以往数位DP不同的是,这里带了个进制进来,而以往做是纯十进制下或者纯二进制下做操作.但是,不管多少进制,原理都是一样的: 3.这里有个小坑,题目中 ...

随机推荐

  1. win7下配置spark

    1.安装jdk(配置JAVA_HOME,CLASSPATH,path) 2.安装scala(配置SCALA_HOME,path) 3.安装spark Spark的安装非常简单,直接去Download ...

  2. Centos7.2部署saltstack

    原文发表于cu:2016-06-23 参考文档: Saltstack安装文档:https://repo.saltstack.com/#rhel saltstack的安装与简单配置,应用. 一.环境 S ...

  3. Vyatta 网络操作系统

    原文发表于:2010-09-19 转载至cu于:2012-07-21 以下是"开源中国社区"写到的: http://www.oschina.net/news/11423/vyatt ...

  4. es6 babel编译

    本文主要参照阮一峰的es6入门,为提高自己写了一份随笔. 原文地址请戳这里  ECMAScript 6 入门 ECMAScript 6是JavaScript语言的下一代标准.因为当前版本的ES6是在2 ...

  5. C++ STL 全排列

    摘自爱国师哥博客https://www.cnblogs.com/aiguona/p/7304945.html 一.概念 从n个不同元素中任取m(m≤n)个元素,按照一定的顺序排列起来,叫做从n个不同元 ...

  6. Python Requests库简单入门

    我对Python网络爬虫的学习主要是基于中国慕课网上嵩天老师的讲授,写博客的目的是为了更好触类旁通,并且作为学习笔记之后复习回顾. 1.引言 requests 库是一个简洁且简单的处理HTTP请求的第 ...

  7. 20162328蔡文琛 week06

    20162328 2017-2018-1 <程序设计与数据结构>第6周学习总结 教材学习内容总结 队列元素按FIFO的方式处理----最先进入的元素最先离开. 队列是保存重复编码k值得一种 ...

  8. 论文爬取 & 词频统计2.0

    一.Github地址      课程项目要求    队友博客 二.具体分工 031602225 林煌伟 :负责C++部分主要功能函数的编写,算法的设计以及改进优化 031602230 卢恺翔 : 爬虫 ...

  9. Alpha-end

    前言 失心疯病源10 团队代码管理github 个人感悟 肝不动了,肝不动了.明天如果见不到我,不要太想我. 站立会议 队名:PMS 530雨勤(组长) 今天完成了那些任务 熬夜肝代码 代码签入git ...

  10. Dijkstra+优先队列 模板

    #include<bits/stdc++.h> using namespace std; #define ll long long ; const ll inf=1e17; struct ...