杭电多校第六场-J-Ridiculous Netizens
Problem Description
The value of a non-empty tree T is equal to w1×w2×⋯×wn. A subtree of T is a connected subgraph of T that is also a tree.
Please write a program to calculate the number of non-empty subtrees of T whose values are not larger than a given number m.
Input
In each test case, there are two integers n,m(1≤n≤2000,1≤m≤106) in the first line, denoting the number of vertices and the upper bound.
In the second line, there are n integers w1,w2,…,wn(1≤wi≤m), denoting the value of each vertex.
Each of the following n−1 lines contains two integers ui,vi(1≤ui,vi≤n,ui≠vi), denoting an bidirectional edge between vertices ui and vi.
Output
Sample Input
Sample Output
题意:
一棵无根树,每个点有权值,询问有多少个联通子图的权值的积等于m 思路
https://www.cnblogs.com/hua-dong/p/11320013.html
考虑对某点,联通块要么经过它要么不经过它 ——> 点分治
对于经过该点的用dp求解
在dfs序上dp,类似于树形依赖背包
dp[i][j]表示 dfs序i之后的乘积为j的方案数
可知 dp[i][j]=(dp[i+1][j/a[dfn[i]]]+dp[i+son[i]][j]) //当前点选/不选
但第二维为m不可行
考虑把<sqrt(M)的和大于sqrt(M)的分开保存,那么前者就是正常的背包,表示当前乘积;后者可以看成以后还可以取多少
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
const int N=1e5+;
const int p=1e9+;
int T,n,m,cnt,sum,root,tim,ans;
struct orz{
int v,nex;}e[N*];
int a[N],last[N],son[N],f[N],dfn[N],dp1[N][],dp2[N][];
bool vis[N];
void add(int x,int y)
{
cnt++;
e[cnt].v=y;
e[cnt].nex=last[x];
last[x]=cnt;
}
void getroot(int x,int fa)
{
son[x]=; f[x]=;
for (int i=last[x];i;i=e[i].nex)
{
if (e[i].v==fa || vis[e[i].v]) continue;
getroot(e[i].v,x);
son[x]+=son[e[i].v];
f[x]=max(f[x],son[e[i].v]);
}
f[x]=max(f[x],sum-son[x]);
if (f[x]<f[root]) root=x;
}
void dfs(int x,int fa)
{
dfn[++tim]=x; son[x]=;
for (int i=last[x];i;i=e[i].nex)
{
if (e[i].v==fa || vis[e[i].v]) continue;
dfs(e[i].v,x);
son[x]+=son[e[i].v];
}
}
void cal()
{
int mm=sqrt(m);
for (int i=;i<=tim+;i++)
{
memset(dp1[i],,sizeof(dp1[i]));
memset(dp2[i],,sizeof(dp2[i]));
}
dp1[tim+][]=;
for (int i=tim;i>=;i--)
{
int x=a[dfn[i]];
for (int j=;j<=min(mm,m/x);j++)
{
int k=j*x;
if (k<=mm) dp1[i][k]=(dp1[i][k]+dp1[i+][j])%p;
else dp2[i][m/k]=(dp2[i][m/k]+dp1[i+][j])%p;
}
for (int j=x;j<=mm;j++)
{
dp2[i][j/x]=(dp2[i][j/x]+dp2[i+][j])%p;
}
for (int j=;j<=mm;j++)
{
dp1[i][j]=(dp1[i][j]+dp1[i+son[dfn[i]]][j])%p;
dp2[i][j]=(dp2[i][j]+dp2[i+son[dfn[i]]][j])%p;
}
}
for (int i=;i<=mm;i++)
{
ans=(ans+dp1[][i])%p;
ans=(ans+dp2[][i])%p;
}
ans=(ans-+p)%p;
}
void work(int x)
{
//cout<<x<<endl;
vis[x]=; tim=;
dfs(root,); //for (int i=1;i<=tim;i++) cout<<dfn[i]<<' '; cout<<endl;
cal();
for (int i=last[x];i;i=e[i].nex)
{
if (vis[e[i].v]) continue;
sum=son[e[i].v];
root=;
getroot(e[i].v,root);
work(root);
}
}
void init()
{
cnt=; ans=;
for (int i=;i<=n;i++) last[i]=,vis[i]=;
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
init();
for (int i=;i<=n;i++) scanf("%d",&a[i]);
int x,y;
for (int i=;i<n;i++)
{
scanf("%d%d",&x,&y);
add(x,y); add(y,x);
}
sum=n; f[]=inf;
getroot(,);
work(root);
printf("%d\n",ans);
}
return ;
}
杭电多校第六场-J-Ridiculous Netizens的更多相关文章
- 2017杭电多校第六场1008 Kirinriki
传送门 Kirinriki Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) To ...
- 2017杭电多校第六场03Inversion
传送门 Inversion Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) To ...
- [2019杭电多校第六场][hdu6638]Snowy Smile(维护区间最大子段和)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6638 题意为在一个平面上任意选择一个长方形,使得长方形内点权和最大. 因为长方形可以任意选择,所以上下 ...
- 2019杭电多校第六场hdu6638 Snowy Smile(线段树+枚举)
Snowy Smile 题目传送门 解题思路 先把y离散化,然后把点按照x的大小进行排序,我们枚举每一种x作为上边界,然后再枚举其对应的每一种下边界.按照这种顺序插入点,这是一个压维的操作,即在线段树 ...
- 2018杭电多校第六场1009(DFS,思维)
#include<bits/stdc++.h>using namespace std;int a[100010];char s[20];int zhiren[100010];vector& ...
- 2017杭电多校第六场1011Classes
传送门 Classes Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Tota ...
- [2019杭电多校第六场][hdu6641]TDL
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6641 题意为求出最小的n,满足(f(n,m)-n)^n=k,其中f(n,m)为第m大的x,其中x满足g ...
- [2019杭电多校第六场][hdu6635]Nonsense Time
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6635 题意是说一开始所有数都冻结,第i秒会解冻第ki个数,求每秒状态下的最长上上升子序列长度. 这种题 ...
- 可持久化线段树的学习(区间第k大和查询历史版本的数据)(杭电多校赛第二场1011)
以前我们学习了线段树可以知道,线段树的每一个节点都储存的是一段区间,所以线段树可以做简单的区间查询,更改等简单的操作. 而后面再做有些题目,就可能会碰到一种回退的操作.这里的回退是指回到未做各种操作之 ...
随机推荐
- setquota - 设置磁盘配额或时间限制
SYNOPSIS(总览) setquota [ -u | -g ] filesystem-name block-soft block-hard inode-soft inode-hard name.. ...
- dotNET面试(二)
值类型与引用类型 1.值类型和引用类型的区别? 值类型包括简单类型.结构体类型和枚举类型,引用类型包括自定义类.数组.接口.委托等. 赋值方式:将一个值类型变量赋给另一个值类型变量时,将复制包含的值. ...
- dotNET面试(一)
1.列举ASP.NET 页面之间传递值的几种方式. 1).使用QueryString, 如....?id=1; response. Redirect().... 2).使用Session变量 3).使 ...
- Node.js require 方法
Node.js 中存在 4 类模块(原生模块和3种文件模块),尽管 require 方法极其简单,但是内部的加载却是十分复杂的,其加载优先级也各自不同
- hdu4857 拓扑排序
题目大意: 糟糕的事情发生啦,现在大家都忙着逃命.但是逃命的通道很窄,大家只能排成一行. 现在有n个人,从1标号到n.同时有一些奇怪的约束条件,每个都形如:a必须在b之前. 同时,社会是不平等的,这些 ...
- 2018/8/26学习Mysql笔记
SELECT * FROM product; #.基本增删改查 #新增 #需求:添加一条数据到产品表 产品名称为苹果手机 卖价为5000 ); #删除 #需求:删除产品表中id=20的数据 ; #需求 ...
- 【leetcode】207. Course Schedule
题目如下: There are a total of n courses you have to take, labeled from 0 to n-1. Some courses may have ...
- openwrt配置内核,加载air720 4G模块的USB串口设备
1,进入openwrt源码包,键入 make menuconfig 2,配置如下 kernel modules ---> USB Support---> <*> kmod-u ...
- QTcpSocket发送结构体
我需要发送的结构体 struct NetDataHeader_t { int nDataType; int nDataSize; }; struct NetDataBase_t { NetDataHe ...
- pic16f877a的AD实验学习
一.主函数 //采集AD值 #include <pic.h> #include "ad.h" #include "usart.h" __CONFIG ...