【HDU5647 BestCoder Round 76 (div1)B】【树形DP】DZY Loves Connecting 一棵树的所有生成子树的大小乘积

本文主要是介绍【HDU5647 BestCoder Round 76 (div1)B】【树形DP】DZY Loves Connecting 一棵树的所有生成子树的大小乘积,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

DZY Loves Connecting

Accepts: 16
Submissions: 169
Time Limit: 4000/2000 MS (Java/Others)
Memory Limit: 262144/262144 K (Java/Others)
问题描述
DZY有一棵nn个结点的无根树,结点按照1\sim n1n标号。DZY喜欢树上的连通集。一个连通集SS是由一些结点组成的集合,满足SS中任意两个结点u,vu,v能够用树上的路径连通,且路径上不经过SS之外的结点。显然,单独一个结点的集合也是连通集。一个连通集的大小定义为它包含的结点个数,DZY想知道所有连通集的大小之和是多少。你能帮他数一数吗?答案可能很大,请对10^9 + 7109+7取模后输出。
输入描述
第一行tt,表示有tt组数据。
接下来tt组数据。每组数据第11行一个数nn。第2\sim n2n行中,第ii行包含一个数p_ipi,表示iip_ipi有边相连。(1\le p_i \le i-1,2\le i\le n1pii1,2in)(n\ge 1n1,所有数据中的nn之和不超过200000200000)
输出描述
每组数据输出一行答案,对10^9 + 7109+7取模。
输入样例
2
1
5
1
2
2
3
输出样例
1
42
Hint
第二个样例中,树的4条边分别为(1,2),(2,3),(2,4),(3,5)。所有连通集分别是{1},{2},{3},{4},{5},{1,2},{2,3},{2,4},{3,5},{1,2,3},{1,2,4},{2,3,4},{2,3,5},{1,2,3,4},{1,2,3,5},{2,3,4,5},{1,2,3,4,5}。

If you need a larger stack size, please use #pragma comment(linker, "/STACK:102400000,102400000") and submit your solution using C++.
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define MP(x,y) make_pair(x,y)
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b>a)a = b; }
template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b<a)a = b; }
const int N = 2e5+10, M = 0, Z = 1e9 + 7, ms63 = 0x3f3f3f3f;
int casenum, casei;
LL sum[N];	//sum[i]表示以i为根节点的所有可能的子树大小之和
LL num[N];	//num[i]表示以i为根节点的子树方案
int n, x;
vector<int>a[N];
LL ans;
void dfs(int x,int fa)
{num[x] = 1;sum[x] = 1;for (int i = a[x].size() - 1; ~i; --i){int y = a[x][i];if (y == fa)continue;dfs(y, x);sum[x] = (sum[x] * (num[y] + 1) + sum[y] * num[x]) % Z;num[x] = num[x] * (num[y] + 1) % Z;}ans = (ans + sum[x]) % Z;
}
int main()
{scanf("%d", &casenum);for (casei = 1; casei <= casenum; ++casei){scanf("%d", &n);for (int i = 1; i <= n; ++i)a[i].clear();for (int i = 2; i <= n; ++i){scanf("%d", &x);a[i].push_back(x);a[x].push_back(i);}ans = 0;dfs(1, 0);printf("%lld\n", ans);}return 0;
}
/*
【trick&&吐槽】
1,BC会爆栈BC会爆栈BC会爆栈BC会爆栈BC会爆栈BC会爆栈BC会爆栈
2,不论是用费马小定理求逆元还是拓展欧几里得求逆元,都要注意要使得gcd()==1这里不光要要求模数Z为素数。因为只是涉及到乘法还无所谓,很多时候还涉及到加法,这就可能会使得方案数为Z的倍数。于是我们要尽量避免求逆元运算。
3,留时间制造hack数据>_<,比如爆栈啦,比如子树的形态构建啦【题意】
一棵树n(2e5)个节点,问所有子树size的乘积。【类型】
树形DP【分析】
首先因为是棵树,所以不妨以1为父节点。
然后我们发现,总归要有一个节点为整棵子树的根节点的。
于是,我们枚举一个点为子树的根节点,然后求其为子树根节点时的子树的大小之和以及子树个数
定义:LL sum[N];	//sum[i]表示以i为根节点的所有可能的子树大小之和LL num[N];	//num[i]表示以i为根节点的子树方案
显然答案就是∑sum[]。然而这个DP要怎么展开呢?
void dfs(int x,int fa)
{num[x] = 1;//只算x作为根节点时的自己,方案数为1sum[x] = 1;//只算x作为根节点时的自己,子树大小和为1for (int i = a[x].size() - 1; ~i; --i){int y = a[x][i];if (y == fa)continue;dfs(y, x);//之前子树的大小会变成*(num[y]+1)种可行方案//新的子树(y)大小会变成sum[y]*num[x]种可行方案sum[x] = (sum[x] * (num[y] + 1) + sum[y] * num[x]) % Z;//子树方案会变成*(num[y]+1)种num[x] = num[x] * (num[y] + 1) % Z;}ans = (ans + sum[x]) % Z;
}
【时间复杂度&&优化】
O(n)*/



这篇关于【HDU5647 BestCoder Round 76 (div1)B】【树形DP】DZY Loves Connecting 一棵树的所有生成子树的大小乘积的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/610416

相关文章

Java实战之利用POI生成Excel图表

《Java实战之利用POI生成Excel图表》ApachePOI是Java生态中处理Office文档的核心工具,这篇文章主要为大家详细介绍了如何在Excel中创建折线图,柱状图,饼图等常见图表,需要的... 目录一、环境配置与依赖管理二、数据源准备与工作表构建三、图表生成核心步骤1. 折线图(Line Ch

MySQL8.0设置redo缓存大小的实现

《MySQL8.0设置redo缓存大小的实现》本文主要在MySQL8.0.30及之后版本中使用innodb_redo_log_capacity参数在线更改redo缓存文件大小,下面就来介绍一下,具有一... mysql 8.0.30及之后版本可以使用innodb_redo_log_capacity参数来更改

浅析如何使用Swagger生成带权限控制的API文档

《浅析如何使用Swagger生成带权限控制的API文档》当涉及到权限控制时,如何生成既安全又详细的API文档就成了一个关键问题,所以这篇文章小编就来和大家好好聊聊如何用Swagger来生成带有... 目录准备工作配置 Swagger权限控制给 API 加上权限注解查看文档注意事项在咱们的开发工作里,API

使用Navicat工具比对两个数据库所有表结构的差异案例详解

《使用Navicat工具比对两个数据库所有表结构的差异案例详解》:本文主要介绍如何使用Navicat工具对比两个数据库test_old和test_new,并生成相应的DDLSQL语句,以便将te... 目录概要案例一、如图两个数据库test_old和test_new进行比较:二、开始比较总结概要公司存在多

java获取图片的大小、宽度、高度方式

《java获取图片的大小、宽度、高度方式》文章介绍了如何将File对象转换为MultipartFile对象的过程,并分享了个人经验,希望能为读者提供参考... 目China编程录Java获取图片的大小、宽度、高度File对象(该对象里面是图片)MultipartFile对象(该对象里面是图片)总结java获取图片

Java使用POI-TL和JFreeChart动态生成Word报告

《Java使用POI-TL和JFreeChart动态生成Word报告》本文介绍了使用POI-TL和JFreeChart生成包含动态数据和图表的Word报告的方法,并分享了实际开发中的踩坑经验,通过代码... 目录前言一、需求背景二、方案分析三、 POI-TL + JFreeChart 实现3.1 Maven

MybatisGenerator文件生成不出对应文件的问题

《MybatisGenerator文件生成不出对应文件的问题》本文介绍了使用MybatisGenerator生成文件时遇到的问题及解决方法,主要步骤包括检查目标表是否存在、是否能连接到数据库、配置生成... 目录MyBATisGenerator 文件生成不出对应文件先在项目结构里引入“targetProje

在MyBatis的XML映射文件中<trim>元素所有场景下的完整使用示例代码

《在MyBatis的XML映射文件中<trim>元素所有场景下的完整使用示例代码》在MyBatis的XML映射文件中,trim元素用于动态添加SQL语句的一部分,处理前缀、后缀及多余的逗号或连接符,示... 在MyBATis的XML映射文件中,<trim>元素用于动态地添加SQL语句的一部分,例如SET或W

C#实现获得某个枚举的所有名称

《C#实现获得某个枚举的所有名称》这篇文章主要为大家详细介绍了C#如何实现获得某个枚举的所有名称,文中的示例代码讲解详细,具有一定的借鉴价值,有需要的小伙伴可以参考一下... C#中获得某个枚举的所有名称using System;using System.Collections.Generic;usi

Python使用qrcode库实现生成二维码的操作指南

《Python使用qrcode库实现生成二维码的操作指南》二维码是一种广泛使用的二维条码,因其高效的数据存储能力和易于扫描的特点,广泛应用于支付、身份验证、营销推广等领域,Pythonqrcode库是... 目录一、安装 python qrcode 库二、基本使用方法1. 生成简单二维码2. 生成带 Log