label {树形dp+机智的优化}
来源:互联网 发布:淘宝等级贷款 编辑:程序博客网 时间:2024/04/28 04:56
【题目描述】
Samjia和Peter不同,他喜欢玩树。所以Peter送给他一颗大小为n的树,节点编号从1到n。
Samjia要给树上的每一个节点赋一个[1,m]之间的权值,并使得有边直接相连的两个节点的权值之差的绝对值 ≥ k。请你告诉Samjia有多少种不同的赋值方案,只用求出答案对10^9+7(1000000007)取模得到的结果。【Sample Input】
(输入数据的第一行包含一个整数 T,测试数据组数。
每组数据的第一行包含三个整数 n、m 和 k。
接下来 n − 1 行,每行包含两个整数 u 和 v, 代表节点 u 和 v 之间有一条树边。)
3
2 2 0
1 2
3 3 2
1 3
1 2
3 3 1
1 2
2 3【Sample Output】
(对于每组数据输出一个整数,代表所求的答案。)
4
2
12【数据范围】
测试点编号 m≤ 特殊约定
1,2 100 无
3,4 10000 无
5,6 10^9 第2-n号节点与1号节点直接相连
7,8 10^9 第i号节点与第i+1号节点直接相连
9,10 10^9 无
【题解】题目看完知道是树形dp
{30%} 裸的随便写,暴力方程:f[i][j]=∏(sigma(f[son[i]][l]))
f[i][j] 表示节点 i 的数值为 j 时的方案数,abs(l-j)<=k;
{60%} 在上式的基础上,对于每个儿子维护前缀和即可;
{100%} 如果我们仔细观察,可以发现一个性质:
对于每个节点x,对于f[x]的中间某一段值可能会出现重复,而重复值段旁的前后两段是对称的。
证明的话,简单的来看,对于叶子节点的每个值答案都是1。那么其父亲累加累乘的时候,到中间就会出现一段相等的值,因为这些值所覆盖的儿子的值域对应的方案数是相等的,而前后两段累加累乘计算的值相同 //貌似怎么解释都有点别扭。。。
所以这些相同的点我们只需要记录其中一个。接下来考虑,不同的点最多有多少个?
从叶子节点往上推,每层最多比上层多 k 个,所以对于任意节点,最多有 (n-1)*k 个不同的值。
//蒟蒻→QAQ个人到了这里其实还是不会打。。。
☆思路和写法整理一下☆
(1) 因为对于每个点有很多相同的,要记录的就是取值范围在:max((n-1)*k,m) 的方案。
(2) 计算每个节点时,先求出当前点 x 取值为1时儿子可取值的和sum{就是一个后缀},随着 x 取值的增大修改sum并计算出当前取值的方案数。具体还是看程序。
#include <cstdio>#include <iostream>#include <cstring> #define LL long long#define mo 1000000007struct edge{ int to,nxt;}e[205];int T,n,m,k,l,cnt,f[105][100005],fi[105]; void add(int u,int v) { e[++cnt].to=v;e[cnt].nxt=fi[u];fi[u]=cnt; } LL qsm(int x,int y) { if (y==1) return x; LL t=qsm(x,y>>1); if (y&1) return t*t%mo*x%mo; else return t*t%mo; } LL sum(int x,int y) { LL s=0; for (int i=y;i<=l;++i) (s+=f[x][i])%=mo; for (int i=m;i>m-l && i>l && i>=y;--i) (s+=f[x][m-i+1])%=mo; int u,v; u=std::max(l+1,y);v=m-l; if (u<=v) (s+=(1ll*f[x][l]*(v-u+1))%mo)%=mo; return s; } void dfs(int x,int fa) { for (int i=1;i<=l;++i) f[x][i]=1; for (int i=fi[x];i;i=e[i].nxt) if (e[i].to!=fa) { dfs(e[i].to,x); int p=sum(e[i].to,k+1); for (int j=1;j<=l;++j) { if (j>k) (p+=f[e[i].to][j-k])%=mo; (p+=mo)%=mo; f[x][j]=1ll*p*f[x][j]%mo; if (j+k<=m) { if (j+k<=l) (p-=f[e[i].to][j+k])%=mo; else if (j+k>m-l) (p-=f[e[i].to][m-j-k+1])%=mo; else (p-=f[e[i].to][l])%=mo; } } } }int main(){ for (scanf("%d\n",&T);T;--T) { scanf("%d%d%d\n",&n,&m,&k); memset(fi,0,sizeof(fi));cnt=0; for (int i=1;i<n;++i) { int u,v;scanf("%d%d\n",&u,&v); add(u,v);add(v,u); } if (!k) printf("%lld\n",qsm(m,n)); else { l=std::min((n-1)*k,m); dfs(1,0); printf("%lld\n",sum(1,1)); } } return 0;}
【题外话】每次打题都会有一些小毛病,有aufeas战god在真是太好了 QAQ QwQ
- label {树形dp+机智的优化}
- 树形DP的一些优化
- vijos p1642(树形dp优化)
- HDU 6161 树形DP + 优化
- dp优化专辑 E - Computer [树形dp]
- 奇奇怪怪的树形dp
- poj 1155 TELE (树形DP+优化)
- zoj3951 Independent Set(树形dp,空间优化)
- hdu6161Big binary tree-(树形dp+空间优化)
- 树形查询的优化
- dp优化专辑 C - Anniversary party [树形dp]
- dp优化专辑 D - Party at Hali-Bula [树形dp]
- dp优化专辑 H -Contestants Division [树形dp]
- dp优化专辑 J -Maximize Game Time [树形dp]
- dp优化专辑 I - Cut the Tree [树形dp]
- 贪吃的九头龙-----树形dp
- 树形DP的一些总结
- 【树形dp】贪吃的九头龙
- jquery刷新页面
- 如何判断论文真正被EI收录? 国际会议都会EI检索吗?IEEE的国际会议,EI数据库核心
- week8(第二波搜索进阶) A -hdu 2553 N皇后问题
- PHP DOM创建生成一个XML文件
- React native的一点浅见
- label {树形dp+机智的优化}
- HDU 1133 Buy the Ticket
- PHP file操作类 判断文件或目录是否存在 复制删除文件等
- struts学习笔记:三种方法配置action
- nyist 38 布线问题(最小生成树kruskal)
- UVA 1400 "Ray, Pass me the dishes!"(线段树)
- 【POJ1753】Flip Game(位压缩+bfs)
- 后验概率直觉解释
- Ajax的介绍