Problem Description

Mr. Bread has a tree T with n vertices, labeled by 1,2,…,n. Each vertex of the tree has a positive integer value wi.

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

The first line of the input contains an integer T(1≤T≤10), denoting the number of test cases.

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

For each test case, print a single line containing an integer, denoting the number of valid non-empty subtrees. As the answer can be very large, output it modulo 10^9+7.

Sample Input

1
5 6
1 2 1 2 3
1 2
1 3
2 4
2 5

Sample Output

14
题意:
一棵无根树,每个点有权值,询问有多少个联通子图的权值的积等于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的更多相关文章

  1. 2017杭电多校第六场1008 Kirinriki

    传送门 Kirinriki Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) To ...

  2. 2017杭电多校第六场03Inversion

    传送门 Inversion Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) To ...

  3. [2019杭电多校第六场][hdu6638]Snowy Smile(维护区间最大子段和)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6638 题意为在一个平面上任意选择一个长方形,使得长方形内点权和最大. 因为长方形可以任意选择,所以上下 ...

  4. 2019杭电多校第六场hdu6638 Snowy Smile(线段树+枚举)

    Snowy Smile 题目传送门 解题思路 先把y离散化,然后把点按照x的大小进行排序,我们枚举每一种x作为上边界,然后再枚举其对应的每一种下边界.按照这种顺序插入点,这是一个压维的操作,即在线段树 ...

  5. 2018杭电多校第六场1009(DFS,思维)

    #include<bits/stdc++.h>using namespace std;int a[100010];char s[20];int zhiren[100010];vector& ...

  6. 2017杭电多校第六场1011Classes

    传送门 Classes Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Tota ...

  7. [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 ...

  8. [2019杭电多校第六场][hdu6635]Nonsense Time

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6635 题意是说一开始所有数都冻结,第i秒会解冻第ki个数,求每秒状态下的最长上上升子序列长度. 这种题 ...

  9. 可持久化线段树的学习(区间第k大和查询历史版本的数据)(杭电多校赛第二场1011)

    以前我们学习了线段树可以知道,线段树的每一个节点都储存的是一段区间,所以线段树可以做简单的区间查询,更改等简单的操作. 而后面再做有些题目,就可能会碰到一种回退的操作.这里的回退是指回到未做各种操作之 ...

随机推荐

  1. 【记录】vue构建项目npm install错误run `npm audit fix` to fix them, or `npm audit` for details

    今天构建vue项目执行npm install初始化后报错 run `npm audit fix` to fix them, or `npm audit` for details 出现这问题控制台会有一 ...

  2. 高逼格企业级MySQL数据库备份方案,原来是这样....

    很多人,这里说的是运维工程师们,一提到写某某方案,很是头疼.不是上某度一统搜索,就是同样一句话在N个群全部群发一遍:“有没有某某方案,可以共享一下的吗??求助,各位大佬们”,估计十有八九,全部石沉大海 ...

  3. Nginx 常用基础模块

    目录 Nginx 常用基础模块 Nginx日志管理 nginx日志切割 Nginx目录索引 Nginx状态监控 Nginx访问控制 Nginx访问限制 Nginx 请求限制配置实战 Nginx Loc ...

  4. go语言从例子开始之Example9.切片

    Slice 是 Go 中一个关键的数据类型,是一个比数组更加强大的序列接口 package main import "fmt" func main() { 不像数组,slice 的 ...

  5. HDU-3333 Turing Tree 分块求区间不同数和

    HDU-3333 Turning Tree 题目大意:先给出n个数字.面对q个询问区间,输出这个区间不同数的和. 题解:这道题有几种解法.这里讲一下用分块解决的方法.( 离线树状数组解法看这里 Hdu ...

  6. java中数据库和VO的一一对应关系

    如图所示,数据库中数据如果有下划线,则JavaVO中删除,除第一个单词外,其他单词首字母大写

  7. 杂谈、 素材资源,没有美工不会ps一样可以美观

    免费素材网站 阿里巴巴矢量图,大部分图标都有颜色像素可选,格式可选3种, http://www.iconfont.cn/plus/home/index?spm=a313x.7781069.199891 ...

  8. Ubuntu下的安装notepad++

    Ubuntu下的安装方法: sudo add-apt-repository ppa:notepadqq-team/notepadqq sudo apt-get update sudo apt-get ...

  9. QT blockingmaster例子学习

    dialog.h: #ifndef DIALOG_H #define DIALOG_H #include <QDialog> #include "masterthread.h&q ...

  10. React的contextType的使用方法简介

    上一篇介绍了Context的使用方法.但是Context会让组件变得不纯粹,因为依赖了全局变量.所以这决定了Context一般不会大规模的使用.所以一般在一个组件中使用一个Context就好. 由于C ...