这题真的神仙,蒟弱表示看题解看不懂……std看了几个小时大概看懂,还有一些细节的东西没有思考。

最难受的是题解和std好像并不是同一个人写的……数组状态不一样……看了好久才看出来f也是前缀和。

F[i][j]表示在点 i 为根的子树中,向下最长轻链长度小于等于 j 的概率。

首先递归下去并求出子树大小,然后枚举重儿子,枚举该点最长轻链长度,再次枚举儿子节点并逐个考虑(感觉和概率充电器(特地从考试总结中搬出来了)那个题有点类似),

假设当前枚举的重儿子是v(i),枚举到儿子节点v(j),x最长轻链长度为k,设gs为v(j)之前考虑的儿子中最长轻链长度为k的概率(因为是前缀和,所以代码中有减这个操作,f同理),如果v(j)=v(i)即v(j)为重儿子,则设fs为以v(j)为根的子树最长轻链长度为k的概率,f[x][k]=gs*f[v(j)][k](v(j)之前考虑的儿子为长度k*以v(j)为根字数长度<=k(此条边为重链所以可以等于))+fs*g[k]-gs*fs(去重),

如果v(j)是轻儿子,则设fs为以v(j)为根的子树最长轻链长度为k-1的概率,f[x][k]=gs*f[v(j)][k-1]+fs*g[k]-gs*fs,大致同上,只是x与v(j)相连的这条边为轻链所以有减1,值得提醒的一点是这里的f[x][k]并不是最终的f[x][k],只是考虑到当前几个儿子时的值,一个儿子一个儿子地向里加。考虑到f数组直接改的话会错,所以用h数组保存,最后加到g数组中清空h,当v(i)为重儿子这个情况考虑玩后将g数组加到f中去,清空g。当前节点x求完后,此时的f数组并不是前缀和,所以需要再次转化。

最后求答案时再次将前缀和转化为单个的值(换来换去好乱啊……)。

还有一点,时间复杂度不容乐观啊,转移的时候如果k循环到了 size[x],那么复杂度可以被卡到 N^3,我们发现当 k>size[v(j)]+1 的时候f[i]没有变,所以只要 k 循环到 size[v(j)]+1 就行了。
每个节点只有在 dp 它父亲时会被枚举成为重儿子,然后最多把整棵树的大小扫一遍,所以复杂度为$n^2$(蒟弱表示并不会证).

ps.有同学问我g数组的含义(好像是没写太清楚),g[k]=∑f[x][l](l<=k)即前缀和,可能用文字描述更好理解点,就是v(j)之前的儿子中最长轻链长度小于等于k的概率。

 1 LL f[3010][3010],g[3010],h[3010],size[3010];
 2 void dfs(int x)
 3 {
 4     size[x]=1;
 5     for(int i=f(x);i;i=n(i))dfs(v(i)),size[x]+=size[v(i)];
 6     LL q=poww(du[x],mod-2);
 7     for(int i=f(x);i;i=n(i))//枚举重儿子
 8     {
 9         for(int j=0;j<=n;j++)g[j]=1;
10         for(int j=f(x);j;j=n(j))
11         {
12             for(int k=0;k<=size[v(j)]+1;k++)
13             {
14                 LL gs=g[k];      if(k)gs-=g[k-1];
15                 LL fs=f[v(j)][k];if(k)fs-=f[v(j)][k-1];
16                 if(v(j)==v(i))h[k]= ((gs*f[v(j)][k]%mod+fs*g[k]%mod-gs*fs)%mod+mod)%mod;
17                 else if(k)
18                 {
19                     fs=f[v(j)][k-1];if(k>1)fs-=f[v(j)][k-2];
20                     h[k]=(  (gs*f[v(j)][k-1]%mod+fs*g[k]%mod-fs*gs%mod)%mod+mod  )%mod;
21                 }
22             }
23             g[0]=h[0],h[0]=0;
24             for(int k=1;k<=size[v(j)]+1;k++)g[k]=(g[k-1]+h[k])%mod,h[k]=0;
25         }
26         for(int j=size[x];j;j--)g[j]=(g[j]-g[j-1]+mod)%mod;
27         for(int j=0;j<=size[x];j++)f[x][j]=(f[x][j]+g[j]*q%mod)%mod;
28     }
29     if(!f(x))f[x][0]=1;
30     for(int i=1;i<=n;i++)f[x][i]=(f[x][i-1]+f[x][i])%mod;
31 }

#include<iostream>
#include<cstdio>
#include<cmath>
#define LL long long
#define int LL
#define MAXN 50100
#define esp 1e-8
#define mod 1000000007
using namespace std;
struct edge
{int u,v,nxt;#define u(x) ed[x].u#define v(x) ed[x].v#define n(x) ed[x].nxt
}ed[5000000];
int first[MAXN],num_e;
#define f(x) first[x]
int n,root;
int du[MAXN],ru[MAXN];LL poww(LL a,int b);
inline void add(int u,int v)
{++num_e;u(num_e)=u;v(num_e)=v;n(num_e)=f(u);f(u)=num_e;
}
inline int read()
{int s=0;char a=getchar();while(a<'0'||a>'9')a=getchar();while(a>='0'&&a<='9'){s=s*10+a-'0';a=getchar();}return s;
}
LL f[3010][3010],g[3010],h[3010],size[3010];void dfs(int x)
{size[x]=1;for(int i=f(x);i;i=n(i))dfs(v(i)),size[x]+=size[v(i)];
//  cout<<x<<" "<<size[x]<<endl;LL q=poww(du[x],mod-2);for(int i=f(x);i;i=n(i))//枚举重儿子{    for(int j=0;j<=n;j++)g[j]=1;for(int j=f(x);j;j=n(j)){for(int k=0;k<=size[v(j)]+1;k++){LL gs=g[k];      if(k)gs-=g[k-1];LL fs=f[v(j)][k];if(k)fs-=f[v(j)][k-1];if(v(j)==v(i))h[k]= ((gs*f[v(j)][k]%mod+fs*g[k]%mod-gs*fs)%mod+mod)%mod;else if(k){fs=f[v(j)][k-1];if(k>1)fs-=f[v(j)][k-2];h[k]=(  (gs*f[v(j)][k-1]%mod+fs*g[k]%mod-fs*gs%mod)%mod+mod  )%mod;}}g[0]=h[0],h[0]=0;for(int k=1;k<=size[v(j)]+1;k++)g[k]=(g[k-1]+h[k])%mod,h[k]=0;}for(int j=size[x];j;j--)g[j]=(g[j]-g[j-1]+mod)%mod;for(int j=0;j<=size[x];j++)f[x][j]=(f[x][j]+g[j]*q%mod)%mod;}if(!f(x))f[x][0]=1;for(int i=1;i<=n;i++)f[x][i]=(f[x][i-1]+f[x][i])%mod;
}
signed main()
{
//  freopen("in.txt","r",stdin);n=read();int a;
//  for(int i=0;i<=n;i++)m[i]=1;for(int i=1;i<=n;i++)        {du[i]=read();for(int j=1;j<=du[i];j++)a=read(),add(i,a),ru[a]++;}bool pdl=1;for(int i=1;i<=n;i++){if(du[i]!=1&&du[i]!=0)pdl=0;if(!ru[i])root=i;}dfs(root);LL ans=0;for(int i=1;i<=n;i++)ans=(ans+i*(f[root][i]-f[root][i-1]+mod)%mod)%mod;printf("%lld\n",ans);
}
LL poww(LL a,int b)
{LL ans=1;while(b){if(b&1)ans=(ans*a)%mod;a=(a*a)%mod;b=b>>1;}return ans;
}

转载于:https://www.cnblogs.com/Al-Ca/p/11188037.html

[***]HZOI20190714 T2熟练剖分相关推荐

  1. B. 熟练剖分(tree) (概率DP)

    一道概率神题,考试时没读清题考完看了学长的玄学题解看了好几个小时 首先f[i][j]表示在点 i 为根的子树中,向下最长轻链长度小于等于 j 的概率. 首先递归下去并求出子树大小,然后枚举重儿子,枚举 ...

  2. Housewife Wind POJ - 2763 倍增LCA+树状数组 或 树链剖分+线段树

    题目 链接:http://poj.org/problem?id=2763 Language:Default Housewife Wind Time Limit: 4000MS   Memory Lim ...

  3. 小清的树链剖分10题日志01 树链剖分种果子 有你好果子吃的

    声明:由于本人能力尚不优 故无法做出解释文章 此文仅为自己日记 感谢你的阅读 作为队里的数据结构选手 2019西安邀请赛的E题 竟然在有机时的情况下 想到了线段树log^2的拆位做法 但是题目路径把自 ...

  4. OI Journal

    佛系更新,哪天想起来就写点. 10.11 班主任硬灌的鸡汤真香 qtmd,简直就是硬扯,说怎么怎么着说不定就能多拿一分两分,一分两分就能割掉好多人 ......螺旋懵圈状,我表示硬憋着不笑 HIAHI ...

  5. BZOJ 4034 树上操作

    熟练剖分 不想写树剖怎么办QwQ 维护每个点\(Ans\) 操作\(1\)就是子树加 操作\(2\)是操作\(1\)的叠加...... 认真分析...... 子树加\(dep\)!!! 写个树状数组节 ...

  6. codeforces 549F Yura and Developers(分治、启发式合并)

    codeforces 549F Yura and Developers 题意 给定一个数组,问有多少区间满足:去掉最大值之后,和是k的倍数. 题解 分治,对于一个区间,找出最大值之后,分成两个区间. ...

  7. 线段树合集——杨子曰算法

    线段树合集--杨子曰算法 这里我把我写的五篇线段树汇总一下: 线段树(一):主要讲了线段树是什么鬼,以及怎样query(←想知道它是什么meaning,点进去!) 线段树(二):体现了线段树真正的价值 ...

  8. BZOJ 4034: [HAOI2015]T2 树链剖分

    4034: [HAOI2015]T2 Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操 ...

  9. 【BZOJ4034】T2,树链剖分练习

    传送门 写在前面:大晚上写题解,明天上午去看电影,可以的~~ 思路:比较裸的树链剖分,比起普通的链剖,这里加了一步对子树(包括自己)的权值修改,这其实很简单,因为我们dfs时任一个子树的区间[L,R] ...

最新文章

  1. 对RTMP视频流进行BitmapData.draw()出错的解决办法
  2. ElasticSearch技术文档
  3. 飞鸽传书(IPMSG)协议(翻译稿)
  4. 滑块 组件_组件制作:如何使用链接的输入创建滑块
  5. Delphi常用字符串函数
  6. IntelliJ IDEA 12.0.3 更新版发布
  7. 小学计算机教案 插入艺术字,小学信息技术《在幻灯片中插入艺术字》说课及反思...
  8. 39节点含太阳能算例
  9. OFDM-训练序列与导频
  10. pb语言是什么计算机语言,pb编程语言排行榜_世界编程语言排行榜 搜狗百科
  11. Flutter Clipboard 粘贴板使用
  12. Going Deeper with Convolutions——GoogLeNet论文翻译——中文版
  13. 什么是ARM TCM内存
  14. 输入三个整数a,b,c。并进行两两相加,最后比较相加和的最大值。
  15. html在360浏览器如何修改字体大小,360浏览器网页中字体大小如何修改
  16. win高分屏下Qt程序的界面适配处理
  17. 从360大战QQ看未来云计算和云存储
  18. SAP FICO F-32和F-44设置默认凭证类型
  19. 辐射度算法(radiosity)原理
  20. 基于matlab的现代通信原理应用

热门文章

  1. python3打包成exe运行 无法定位程度输入点_Pyinstaller递归错误解决方案
  2. [HNOI2007] 分裂游戏
  3. [GCJ] Qualification Round 2017
  4. Java提高篇——静态代码块、构造代码块、构造函数以及Java类初始化顺序
  5. 关于cookie使用的几个方法
  6. Applying a Color Wash to Images
  7. php image处理,php 中图像压缩处理类(二)imageutil.php
  8. DMA流程简介--CPU/内存/网卡之间的交互
  9. List大坑集「锦」
  10. Hive文件数创建过多的问题