[HDU 6643] Ridiculous Netizens(点分治+根号分治+dp)

HDU 6643 Ridiculous Netizens

problem

hdu6643

题目大意:给定一棵无根树,以及每个点的点权 wiw_iwi

定义一个连通块的价值为连通块内点的点权之积。

求有多少个连通块价值 ≤m\le mm

n≤2e3,m≤1e6n\le 2e3,m\le 1e6n2e3,m1e6

solution

取一个点作根,将无根树转化为有根树。

统计连通块包含根节点的情况,不包含根就分裂成若干个互不相同的子树,变成子问题,重复以上操作。

选取重心作根,点分治。

这是大致框架,问题就在于怎么快速计算包含根的符合要求的连通块个数。

observation:因为是连通块,如果父亲不选,那么其所有子孙都不可能入选。

所以我们考虑使用 dfn 序重编号,从后往前做。

dpi,j:dfndp_{i,j}:dfndpi,j:dfn 序编号到为 iii 的点为止,价值为 jjj 的连通块个数。

  • 如果要选当前点,子孙是可选可不选的,从 dfndfndfn 序后一个直接转移。

    dfn[i]:dfndfn[i]:dfndfn[i]:dfn 序为 iii 的原对应点】

    dp(i,j×wdfn[i])←dp(i+1,j)dp(i,j\times w_{dfn[i]})\leftarrow dp(i+1,j)dp(i,j×wdfn[i])dp(i+1,j)

  • 如果不选,就必须跳过其所有子孙。【siz[i]:isiz[i]:isiz[i]:i 子树的大小】

    dp(i,j)←dp(i+sizi,j)dp(i,j)\leftarrow dp(i+siz_i,j)dp(i,j)dp(i+sizi,j)

注意到 nmnmnm 的范围,根本开不下 2e92e92e9 的数组。

那就——分块!

按照连通块价值的大小分块, ≤m\le\sqrt{m}m>m>\sqrt{m}>m

  • ≤m\le \sqrt{m}m

    fi,j:f_{i,j}:fi,j:iii 为止,价值为 jjj 的连通块个数。

    正常地向上面一样进行背包转移。

  • >m>\sqrt{m}>m

    fi,j:f_{i,j}:fi,j:iii 为止,价值还能装下 jjj 的连通块个数。即价值已经为 mj\frac{m}{j}jm 的联通块个数。

具体可见代码实现。

code

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define maxn 2005
#define maxm 1005
#define int long long
#define mod 1000000007
#define inf 0x7f7f7f7f
struct node { int to, nxt; }E[maxn << 1];
int cnt, tot, n, m, Max, N, M, T, root, ans;
bool vis[maxn];
int w[maxn], siz[maxn], dfn[maxn], head[maxn];
int f[maxn][maxm], g[maxn][maxm];void addedge( int u, int v ) {E[tot] = { v, head[u] }, head[u] = tot ++;E[tot] = { u, head[v] }, head[v] = tot ++;
}void get_root( int u, int fa ) {int maxson = 0; siz[u] = 1;for( int i = head[u];~ i;i = E[i].nxt ) {int v = E[i].to;if( vis[v] or v == fa ) continue;get_root( v, u );siz[u] += siz[v];maxson = max( maxson, siz[v] );}maxson = max( maxson, N - siz[u] );if( maxson < Max ) Max = maxson, root = u;
}void dfs( int u, int fa ) {dfn[++ cnt] = u, siz[u] = 1;for( int i = head[u];~ i;i = E[i].nxt ) {int v = E[i].to;if( v == fa or vis[v] ) continue;else dfs( v, u ), siz[u] += siz[v];}
}void calc() {cnt = 0, dfs( root, 0 );for( int i = 1;i <= cnt + 1;i ++ ) {memset( f[i], 0, sizeof( f[i] ) );memset( g[i], 0, sizeof( g[i] ) );} f[cnt + 1][1] = 1;for( int i = cnt;i;i -- ) {int x = w[dfn[i]];//要选dfn[i]for( int j = 1;j <= min( M, m / x );j ++ ) { //枚举后i+1个一共使用了j空间 如果后i个乘积不超过M 做普通背包int k = j * x;if( k <= M ) f[i][k] = ( f[i][k] + f[i + 1][j] ) % mod;else g[i][m / k] = ( g[i][m / k] + f[i + 1][j] ) % mod;//否则就是剩下了m/(j*x)的贡献//这里是用的f[i+1][j]在更新 只代表了后i+1乘积不超过M的情况}for( int j = x;j <= M;j ++ )//这里使用的g[i+1][j]在更新 只代表了后i+1乘积超过M的情况g[i][j / x] = ( g[i][j / x] + g[i + 1][j] ) % mod;//不选for( int j = 1;j <= M;j ++ ) {f[i][j] = ( f[i][j] + f[i + siz[dfn[i]]][j] ) % mod;g[i][j] = ( g[i][j] + g[i + siz[dfn[i]]][j] ) % mod;}}for( int i = 1;i <= M;i ++ )ans = ( ans + f[1][i] + g[1][i] ) % mod;ans = ( ans - 1 + mod ) % mod; //减去空连通块的贡献
}void dfs( int u ) {vis[u] = 1;calc();for( int i = head[u];~ i;i = E[i].nxt ) {int v = E[i].to;if( vis[v] ) continue;Max = inf, N = siz[v];get_root( v, u );dfs( root );}
}signed main() {scanf( "%lld", &T );while( T -- ) {tot = 0; memset( head, -1, sizeof( head ) );scanf( "%lld %lld", &n, &m );for( int i = 1;i <= n;i ++ ) vis[i] = 0, scanf( "%lld", &w[i] );for( int i = 1, u, v;i < n;i ++ ) {scanf( "%lld %lld", &u, &v );addedge( u, v );}M = sqrt( m );Max = inf, N = n;get_root( 1, 0 );dfs( root );printf( "%lld\n", ans );ans = 0;}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/316755.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SP422 TRANSP2 - Transposing is Even More Fun(Burnside引理,莫比乌斯反演)

解析 很巧妙的题。 关键是要利用好边长为2的整数次幂的性质。 对下标从1开始党极不友好。 首先显然答案就是 2ab2^{ab}2ab -环。 让下标均从0开始。 对于一个点 (i,j)(i,j)(i,j)&#xff0c;它原来的内存地址为 i∗2aji*2^aji∗2aj&#xff0c;转置后的地址为 j∗2bij*2^bij∗…

Fireworks(2020 ICPC南京)

Fireworks 题意&#xff1a; 你每做一个烟花要n分钟&#xff0c;释放已做好的所有烟花需要m分钟&#xff0c;每只烟花成功释放的概率为p。问你在采取最优策略的前提下&#xff0c;直到成功释放第一个烟花时最小的期望时间花费。 题解&#xff1a; 最佳策略是&#xff1a;每…

ASP.NET Core 沉思录 - ServiceProvider 的二度出生

ASP.NET Core 终于将几乎所有的对象创建工作都和依赖注入框架集成了起来。并对大部分的日常工作进行了抽象。使得整个框架扩展更加方便。各个部分的集成也更加容易。今天我们要思考的部分仍然是从一段每一个工程中都大同小异的代码开始的。IWebHostBuilder CreateWebHostBuilde…

[SPOJ - FTOUR2] Free tour II(点分治 + 背包dp + 启发式合并)

SPOJ - FTOUR2 Free tour II problem 给定一棵树&#xff0c;以及 mmm 个拥挤城市编号&#xff0c;选择一条最多包含 kkk 个拥挤城市的简单路径。 每条边有一个有趣度 www&#xff0c;可正可负。简单路径的价值定义为包含边的有趣度之和。 求最大价值。n≤2e5,∣w∣≤1e4n\…

PKUSC2022 游记

前言 1001822698014095235。 题的难度感觉比去年难不少&#xff0c;主要的体现在于两天的T1都没有之前那么可做了&#xff0c;在信息差的影响下几乎成了两场崩盘场。 由于比赛时间变短的原因&#xff0c;模拟反而比历年简单不少。 遗憾&#xff1a; d1t3的网络流莫名其妙无法…

Acwing 216. Rainbow的信号

Acwing 216. Rainbow的信号 题意&#xff1a; 给你n个数&#xff0c;在这n个数中&#xff0c;等概率地选取两个数l&#xff0c;r&#xff0c;如果l>r,则交换l,r 把信号中的第 l 个数到第 r 个数取出来&#xff0c;构成一个数列 P。 A 部分对话的密码是数列 P 的 xor 和的…

微软开源故事 | 开启 .NET 开源革命

如今&#xff0c;在微软构建开源软件是很正常的一件事——但早在2007年&#xff0c;我开始在微软工作时&#xff0c;情况并非如此。我们花了几年的时间才找到正确的方法&#xff0c;顺利开启了微软的开源之路。但是&#xff0c;如今我们已取得胜利&#xff0c;可以面带微笑地回…

【无码专区9】序列统计(带权并查集 + 前缀和建边 + dp)

因为只有std&#xff0c;没有自我实现&#xff0c;所以是无码专区 主要是为了训练思维能力 solution才是dls正解&#xff0c;但是因为只有潦草几句&#xff0c;所以大部分会有我自己基于正解上面的算法实现过程&#xff0c;可能选择的算法跟std中dls的实现不太一样。 std可能…

Acwing 217. 绿豆蛙的归宿

Acwing 217. 绿豆蛙的归宿 题意&#xff1a; 给出一个有向无环的连通图&#xff0c;起点为 1&#xff0c;终点为 N&#xff0c;每条边都有一个长度。 数据保证从起点出发能够到达图中所有的点&#xff0c;图中所有的点也都能够到达终点。 绿豆蛙从起点出发&#xff0c;走向…

LNOI2022:游记

前言 The world is cruel. 真的为身边的一些人感到可惜… Day -1 PKUSC刚刚考完&#xff0c;然后就要省选了&#xff1f; 板子实在是看的够够的了。 然而还是不想深度做题&#xff0c;看了看APIO的practise&#xff0c;T1写完发现偶数还得特别做&#xff0c;就感觉很麻烦&…

合肥.NET技术社区首次线下聚会全程回顾【多图】

2019年3月16日对于合肥.NET来说是一个特别的日子&#xff0c;因为这是合肥.NET技术社区首次非正式线下聚会&#xff01;这次聚会受场地限制&#xff08;毕竟是聚餐的形式&#xff09;&#xff0c;即使换成了小椅子后&#xff0c;最多也只能容纳24个人&#xff0c;所以还有一些小…

【无码专区10】第K大查询(双向链表 /主席树+st表)

已自我实现&#xff0c;但还是归入无码专区序列。哈哈哈哈哈 对于my idea部分&#xff0c;我的每一个想法都实现了&#xff0c;可供参考。 problem 给定一个 1∼n1\sim n1∼n 的排列和 kkk&#xff0c;求所有 r−l1≥kr-l1\ge kr−l1≥k 的区间 [l,r][l,r][l,r] 中的第 kkk 大…

SignalR第一节-在5分钟内完成通信连接和消息发送

前言首先声明&#xff0c;这又是一个小白从入门到进阶系列。 SignalR 这个项目我关注了很长时间&#xff0c;中间好像还看到过微软即将放弃该项目的消息&#xff0c;然后我也就没有持续关注了&#xff0c;目前的我项目中使用的是自己搭建的 WebSocket &#xff0c;连接管理和消…

P5327 [ZJOI2019]语言(线段树合并、生成树)

解析 只会扫描线树剖的三只log&#xff08;悲 考虑对每个 uuu 考虑合法的 vvv 的集合&#xff0c;必然是一个联通块。 进一步的&#xff0c;观察到这个联通块就是由所有经过 uuu 的路径的端点形成的最小生成树。 我们有一个最小生成树的经典结论&#xff1a;最小生成树边权和…

【学习笔记】信息学竞赛中的概率与期望小结

信息竞赛——概率与期望事件事件的蕴含、包含事件的互斥事件的对立事件的和&#xff08;并&#xff09;事件的积&#xff08;交&#xff09;事件的差概率事件的独立性全概率公式贝叶斯公式概率DP&#xff08;竞赛中的考察&#xff09;期望&#xff08;竞赛中的考察&#xff09;…

Acwing 218. 扑克牌

Acwing 218. 扑克牌 题意&#xff1a; 一副扑克牌(54张)&#xff0c;问得到A 张黑桃、B 张红桃、C 张梅花、D 张方块需要翻开的牌的张数的期望值 E 是多少&#xff1f; 如果翻开的牌是大王或者小王&#xff0c;Admin 将会把它作为某种花色的牌放入对应堆中&#xff0c;使得放…

尝试:Script Lab,快速 O365 开发工具//SL01)

《前言》Script Lab 我希望有一个系列&#xff08;连载&#xff09;&#xff0c;可是我挺担心没偿没有能力去驾驭它。虽然早年前己经接触过&#xff0c;但一直未有下决心开始 Office 365 的开发之旅&#xff0c;虽然一直被光标老师所鼓舞&#xff0c;但是我心有旁骛还没有真正做…

P3710 方方方的数据结构(kd-tree)

解析 写吐了… 一开始觉得线段树分治直接做就行简直是个伞兵题&#xff0c;写完挂掉才想起来线段树分治会打乱操作顺序导致全假… 重构吧&#xff01; 炸裂之下去贺题解&#xff0c;std做法 O(mmlog⁡m)O(m\sqrt m\log m)O(mm​logm) 令人谔谔&#xff0c;但kd-tree做法确实挺…

[POJ 3709] K-Anonymous Sequence(斜率优化dp / 动态维护凸包)

K-Anonymous Sequence看了两年前自己的博客&#xff0c;真的好青涩&#xff0c;连 markdown 都不太会用。 确实观赏感不是很好。 学习真的是慢慢积累的过程&#xff0c;以前感觉理解很困难的事&#xff0c;随着知识的增长&#xff0c;现在都基本悟了。 problem POJ3709 so…

Keiichi Tsuchiya the Drift King

Keiichi Tsuchiya the Drift King 题意&#xff1a; 给定一辆小车长宽分别为 b&#xff0c;a&#xff0c;轨道的圆弧部分半径为 r&#xff0c;圆弧对应的角度为 d&#xff0c;求出小车能通过轨道的最小轨道宽度 w。 题解&#xff1a; 我们考虑小车处于什么状态会使弯道最宽…