一道概率神题,考试时没读清题考完看了学长的玄学题解看了好几个小时

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

首先递归下去并求出子树大小,然后枚举重儿子,枚举该点最长轻链长度,再次枚举儿子节点并逐个

假设当前枚举的重儿子是to1,枚举到儿子节点to2,x最长轻链长度为k,设gs为v(to2)之前考虑的儿子中最长轻链长度为k的概率如果v(to1)=v(to2)即v(to2)为重儿子,则设fs为以v(to2)为根的子树最长轻链长度为k的概率:

h[k]=(fs*g[k]%mod+gs*f[to2][k]%mod-gs*fs+mod)%mod;     

如果v(to2)是轻儿子,则设fs为以v(to2)为根的子树最长轻链长度为k-1的概率,

h[k]=(fs*g[k]%mod+gs*f[to2][k-1]%mod-gs*fs+mod)%mod;

只是x与to2相连的这条边为轻链所以有减1,值得提醒的一点是这里的f[x][k]并不是最终的f[x][k],只是考虑到当前几个儿子时的值,一个儿子一个儿子地向里加。考虑到f数组直接改的话会错,所以用h数组保存,最后加到g数组中清空h,当to1为重儿子这个情况考虑玩后将g数组加到f中去,清空g。当前节点x求完后,此时的f数组并不是前缀和,所以需要再次转化。

最后求答案时再次将前缀和转化为单个的值

至于此题为啥求概率却用一堆整数想乘是因为题目要求

我们发现每一层的1/chu[x]即为分母,所以可以直接乘逆元,而这样的相加不会影响结果

所以最后i*f[x][i]就是期望。

  1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<string>
5 #include<algorithm>
6 #include<vector>
7 #include<cmath>
8 #include<stack>
9 #include<queue>
10 #define MAXN 3101
11 #define ll long long
12 using namespace std;
13 const ll mod=1e9+7;
14 struct node{ll to,n;}e[MAXN];
15 ll head[MAXN],tot;
16 void add(ll u,ll v){e[++tot].to=v;e[tot].n=head[u];head[u]=tot;}
17 ll size[MAXN];
18 ll f[MAXN][MAXN],g[MAXN],h[MAXN];
19 ll n;ll chu[MAXN];
20 ll pow(ll x,ll y)
21 {
22 ll ans=1;
23 while(y)
24 {
25 if(y&1)ans=(ans*x)%mod;
26 x=(x*x)%mod;
27 y>>=1;
28 }
29 return ans%mod;
30 }
31 void DFS(ll x)
32 {
33 size[x]=1;
34 for(ll i=head[x];i;i=e[i].n)
35 {
36 ll to=e[i].to;
37 DFS(to);
38 size[x]+=size[to];
39 }
40 ll ppow=pow(chu[x],mod-2ll)%mod;
41 for(ll i=head[x];i;i=e[i].n)
42 {
43 for(ll i=0;i<=size[x]+1;++i)g[i]=1;
44 for(ll j=head[x];j;j=e[j].n)
45 {
46 ll fs,gs;
47 ll to1=e[i].to;ll to2=e[j].to;
48 for(ll k=0;k<=size[to2]+1;++k)
49 {
50 if(to1==to2){
51 if(!k)fs=f[to2][k];else fs=f[to2][k]-f[to2][k-1];
52 if(!k)gs=g[k]; else gs=g[k]-g[k-1];
53 h[k]=(fs*g[k]%mod+gs*f[to2][k]%mod-gs*fs+mod)%mod;
54 // printf("h[%lld]=%lld\n",k,h[k]);
55 }
56 else if(k){
57 if(!k)fs=f[to2][k-1];else fs=f[to2][k-1]-f[to2][k-2];
58 if(!k)gs=g[k]; else gs=g[k]-g[k-1];
59 h[k]=(fs*g[k]%mod+gs*f[to2][k-1]%mod-gs*fs+mod)%mod;
60 }
61 }
62 g[0]=h[0];h[0]=0;
63 for(ll k=1;k<=size[to2]+1;++k)
64 {
65 g[k]=(g[k-1]+h[k])%mod;h[k]=0;
66 }
67 }
68 for(ll j=size[x]+1;j>=1;--j)
69 {
70 g[j]=(g[j]-g[j-1]+mod)%mod;//printf("g[%lld]=%lld\n",j,g[j]);
71 }
72 for(ll j=0;j<=size[x]+1;++j)
73 {
74 f[x][j]=(f[x][j]+g[j]*ppow%mod)%mod;
75 // printf("f[%lld][%lld]=%lld\n",x,j,f[x][j]);
76 }
77 // printf("p=%lld\n",pow(chu[x],mod-2ll));
78 }
79 if(head[x]==0)f[x][0]=1;
80 for(ll i=1;i<=size[x]+1;++i)
81 {
82 f[x][i]=(f[x][i]+f[x][i-1]+mod)%mod;
83 // printf("f[%lld][%lld]=%lld\n",x,i,f[x][i]);
84 }
85 }
86 ll ru[MAXN];ll si=1;
87 int main()
88 {
89 scanf("%lld",&n);
90 for(ll i=1;i<=n;++i){
91 scanf("%lld",&chu[i]);
92 for(ll j=1;j<=chu[i];++j){
93 ll y;
94 scanf("%lld",&y);
95 add(i,y);ru[y]++;
96 }
97 }
98 ll root=0;
99 for(ll i=1;i<=n;++i){
100 if(ru[i]==0)
101 root=i;
102 }
103 DFS(root);
104 ll ans=0;
105 for(ll i=1;i<=size[root]+1;++i)
106 {
107 ans=(ans+i*(f[root][i]-f[root][i-1]%mod)+mod)%mod;
108 }
109 printf("%lld\n",(ans+mod)%mod);
110 }

【模拟7.14】B. 熟练剖分(tree) (概率DP)的更多相关文章

  1. 熟练剖分(tree) 树形DP

    熟练剖分(tree) 树形DP 题目描述 题目传送门 分析 我们设\(f[i][j]\)为以\(i\)为根节点的子树中最坏时间复杂度小于等于\(j\)的概率 设\(g[i][j]\)为当前扫到的以\( ...

  2. 20210501 序列,熟练剖分(tree),建造游乐园(play)

    考场 \(65+5+0\),并列 rk2 最高分 \(55+10+10\) T1:等比数列可以写作 \(q^kx\),发现 \(q\le1000\) 且有一档分为 \(a_i\le100\),想到 \ ...

  3. HZOI2019熟练剖分(tree)

    题目大意:https://www.cnblogs.com/Juve/articles/11186805.html 题解: 先给出官方题解: 其实这题跟期望没什么关系,因为E=$\sum_\limits ...

  4. 【XSY2332】Randomized Binary Search Tree 概率DP FFT

    题目描述 \(\forall 0\leq i<n\),求有多少棵\(n\)个点,权值和优先级完全随机的treap的树高为\(i\). \(n\leq 30000\) 题解 设\(f_{i,j}\ ...

  5. [CSP-S模拟测试]:石头剪刀布(rps)(概率DP)

    题目传送门(内部题9) 输入格式 第一行一个整数$n$.接下来$n$行每行$3$个非负整数$r_i,p_i,s_i$. 输出格式 一行一个实数表示答案.当你的答案与标准答案的绝对或相对误差不超过${1 ...

  6. NOIP模拟测试3「序列·熟练剖分·建造游乐园(play)」

    ---恢复内容开始--- 序列 刚调出来样例就A了,假装是水题. 因为是乱序,我们要求出来每两项之间最小公比,而不是直接比 求出来每两项之间最小公比,然后扫一遍就完了.(还要注意重复情况) 那么问题就 ...

  7. 20190716NOIP模拟赛T1 礼物(概率dp+状压)

    题目描述 夏川的生日就要到了.作为夏川形式上的男朋友,季堂打算给夏川买一些生 日礼物. 商店里一共有种礼物.夏川每得到一种礼物,就会获得相应喜悦值Wi(每种 礼物的喜悦值不能重复获得). 每次,店员会 ...

  8. [CSP-S模拟测试]:糊涂图(概率DP)

    题目传送门(内部题76) 输入格式 第一行输入三个空格隔开的整数$n,m,s$表示随机加一条边之前的糊涂图的点数,边数,以及起点的编号. 接下来$m$行,每行两个空格隔开的整数$a,b$表示从$a$到 ...

  9. JZOJ 【NOIP2017提高A组模拟9.14】捕老鼠

    JZOJ [NOIP2017提高A组模拟9.14]捕老鼠 题目 Description 为了加快社会主义现代化,建设新农村,农夫约(Farmer Jo)决定给农庄里的仓库灭灭鼠.于是,猫被农夫约派去捕 ...

随机推荐

  1. ConcurrentHashMap源码解读三

    今天首先讲解helpTransfer方法 final Node<K,V>[] helpTransfer(Node<K,V>[] tab, Node<K,V> f) ...

  2. CRM系统推动教育行业数字化转型

    目前,教育培训的潜在市场规模巨大,并且保持着迅猛的发展态势.同时,随着众多外资企业不断涌入中国市场,与国内大大小小的培训机构展开竞争,所以教育行业的竞争也是非常的激烈.传统的教育行业亟待数字化转型,才 ...

  3. .Net Core·寄托于IIS的REST服务405的问题

    阅文时长 | 0.48分钟 字数统计 | 828.8字符 主要内容 | 1.引言&背景 2.声明与参考资料 『.Net Core·寄托于IIS的REST服务405的问题』 编写人 | SCsc ...

  4. 真正的原生JS数据双向绑定(实时同步)

    真正的原生JS数据双向绑定(实时同步) 接触过vue之后我感觉数据双向绑定实在是太好用了,然后就想着到底是什么原理,今天在简书上看到了一位老师的文章 js实现数据双向绑定 然后写出了我自己的代码 wi ...

  5. 使用基于centos7 dbus问题总结

    Authorization not available. Check if polkit Authorization not available. Check if polkit service is ...

  6. 联想ThinkServer服务器安装CentOS7 Redhat7系统 驱动R110i RAID卡

    1.下载对应版本的驱动(因为联想没有CentOS的驱动用redhat的驱动就可以). 2.进入BIOS里,在高级设置里找到SATA设置,把SATA模式改成RAID(重启后配置raid),sSATA模式 ...

  7. who -b

    ~]# who -b 系统引导 2020-05-03 19:57[root@localhost ~]# who -r 运行级别 5 2020-05-03 19:58

  8. setting>SSH>sessions setting>勾选ssh Keepalive[ MobaXterm】设置保持SSH连接

    [ MobaXterm]设置保持SSH连接 ssh远程连接会在无操作时自动断开连接.为了保持程序运行和连接,需要设置保持连接. 1.MobaXterm如果使用了MobaXterm客户端,那么需要在设置 ...

  9. k8s集群部署(2)

    一.利用ansible部署kubernetes准备阶段 1.集群介绍 基于二进制方式部署k8s集群和利用ansible-playbook实现自动化:二进制方式部署有助于理解系统各组件的交互原理和熟悉组 ...

  10. CentOS7安装vncserver(启动失败及连接黑屏解决办法)

    CentOS7安装vncserver(启动失败及连接黑屏解决办法) 转载weixin_34167043 最后发布于2017-11-09 15:11:00 阅读数 42  收藏 展开 AutoSAR入门 ...