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. VoIP系统大盘点

    一.VoIP拓扑 PBX是程控交换机,程控交换机有实体交换机和软件模拟的交换机. 软件模拟的交换机,即交换机服务器,常用开源的sip服务器有asterisk,freepbx, opensip, fre ...

  2. shell函数的存储和显示

  3. RabbitMQ学习第三记:发布/订阅模式(Publish/Subscribe)

    工作队列模式是直接在生产者与消费者里声明好一个队列,这种情况下消息只会对应同类型的消费者. 举个用户注册的列子:用户在注册完后一般都会发送消息通知用户注册成功(失败).如果在一个系统中,用户注册信息有 ...

  4. translation of 《deep learning》 Chapter 1 Introduction

    原文: http://www.deeplearningbook.org/contents/intro.html Inventors have long dreamed of creating mach ...

  5. vue-cli脚手架快速搭建项目

    前言 vue-cli 是一个官方发布 vue.js 项目脚手架,使用 vue-cli 可以快速创建 vue 项目. 准备工作 在搭建一个vue项目之前,需要先安装好node.js和cnpm. 虽然np ...

  6. ajax中json格式数据如何朝后端发送数据

  7. 微信jssdk安卓机分享QQ好友和QQ空间出现{"errMsg":"shareQQ:fail"}

    使用ajax请求appid之类的配置,然后进行wx.config和wx.ready,苹果机上是完全OK的,但是安卓机上十次有九次是失败,只有一次能成功,百度了一下,有人说是参数有空格,有人说是微信bu ...

  8. sql中简单的触发器功能

    触发器分为DML触发器和DDL触发器DML触发器包含After触发器,执行insert update delete语句后会触发after触发器,会事务回滚DML触发器还包含instead of触发器, ...

  9. BZOJ 3105: [cqoi2013]新Nim游戏(线性基)

    解题思路 \(nim\)游戏先手必胜的条件是异或和不为\(0\),也就是说第一个人拿走了若干堆后不管第二个人怎么拿都不能将剩余堆的异或和变成\(0\).考虑线性基,其实就是每个数对线性基都有贡献,任何 ...

  10. VIEW当中自定义属性的使用

    主要有三种方法可以实现自定义属性. 第一种方法,直接设置属性值,通过attrs.getAttributeResourceValue拿到这个属性值. (1)在xml文件中设置属性值 [html] vie ...