题目:https://loj.ac/problem/2542

可以最值反演。注意 min 不是独立地算从根走到每个点的最小值,在点集里取 min ,而是整体来看,“从根开始走到点集中的任意一个点就停下”的期望步数。

设 f[ i ] 表示从根走到 i ,再走期望几步就能走到点集中的某个点。有 \( f[i]=\frac{1}{d[i]}\sum\limits_{j}(f[j]+1) \) ( j 是和 i 有边的点)

于是要“树上高斯消元”。其实就是尝试写成 \( f[i]=a[i]*f[st]+b[i] \) (st 是根)之类的形式,从而让系数的转移有方向,然后根据 \( a[st] \) 和 \( b[st] \) 算 \( f[st] \) 。

为了有方向,这里设 \( f[i]=a[i]*f[st]+b[i]*f[fa]+c[i] \) (有 \( a[i]*f[st] \) 是为了算 \( f[st] \) )

\( f[i]=\frac{1}{d[i]}f[fa]+\frac{1}{d[i]}+\frac{1}{d[i]}\sum\limits_{j \in child}f[j]+\frac{d[i]-1}{d[i]} \)

\( d[i]*f[i]=f[fa]+d[i]+\sum\limits_{j \in child}a[j]f[st]+\sum\limits_{j \in child}b[j]f[i]+\sum\limits_{j \in child}c[j] \)

\( (d[i]-\sum\limits_{j \in child}b[j])f[i]=\sum\limits_{j \in child}a[j]f[st]+f[fa]+d[i]+\sum\limits_{j \in child}c[j] \)

然后对于每个点集可以树形DP地算。如果走到了点集中的点,那么 a[cr] 、b[cr] 、c[cr] 都是 0 ,并且直接 return 即可。

最值反演的时候求子集的和可以用 fmt 算。那个 -1 的系数只要在初值的时候体现一下就行了。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
int rdn()
{
int ret=;bool fx=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')fx=;ch=getchar();}
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return fx?ret:-ret;
}
const int N=,M=(<<)+,mod=;
int upt(int x){if(x<)x+=mod;if(x>=mod)x-=mod;return x;}
int pw(int x,int k)
{int ret=;while(k){if(k&)ret=(ll)ret*x%mod;x=(ll)x*x%mod;k>>=;}return ret;} int n,st,hd[N],xnt,to[N<<],nxt[N<<],dg[N],a[N],b[N],c[N];
int bin[N],f[M],ct[M];
void add(int x,int y){to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;dg[x]++;}
void dfs(int cr,int fa,int s)
{
a[cr]=b[cr]=c[cr]=;int tp=;
if(s&bin[cr-])return;//////return!
for(int i=hd[cr],v;i;i=nxt[i])
if((v=to[i])!=fa)
{
dfs(v,cr,s);
a[cr]=upt(a[cr]+a[v]); c[cr]=upt(c[cr]+c[v]); tp=upt(tp+b[v]);
}
tp=pw(upt(dg[cr]-tp),mod-);
a[cr]=(ll)a[cr]*tp%mod; b[cr]=tp; c[cr]=(ll)(c[cr]+dg[cr])*tp%mod;
}
void fmt()
{
for(int i=;i<bin[n];i<<=)
for(int s=;s<bin[n];s++)
if(s&i)f[s]=upt(f[s]+f[s^i]);
}
int main()
{
n=rdn();int Q=rdn();st=rdn();
for(int i=,u,v;i<n;i++)
u=rdn(),v=rdn(),add(u,v),add(v,u);
bin[]=;for(int i=;i<=n;i++)bin[i]=bin[i-]<<;
for(int s=;s<bin[n];s++)ct[s]=ct[s-(s&-s)]+;
for(int s=;s<bin[n];s++)
{
dfs(st,,s);f[s]=(ll)c[st]*pw(upt(-a[st]),mod-)%mod;
if((ct[s]&)==)f[s]=upt(-f[s]);
}
fmt();
while(Q--)
{
n=rdn();int s=;
for(int i=;i<=n;i++)s|=bin[rdn()-];
printf("%d\n",f[s]);
}
return ;
}

LOJ 2542 「PKUWC2018」随机游走 ——树上高斯消元(期望DP)+最值反演+fmt的更多相关文章

  1. Loj #2542. 「PKUWC2018」随机游走

    Loj #2542. 「PKUWC2018」随机游走 题目描述 给定一棵 \(n\) 个结点的树,你从点 \(x\) 出发,每次等概率随机选择一条与所在点相邻的边走过去. 有 \(Q\) 次询问,每次 ...

  2. LOJ #2542「PKUWC2018」随机游走

    $ Min$-$Max$容斥真好用 $ PKUWC$滚粗后这题一直在$ todolist$里 今天才补掉..还要更加努力啊.. LOJ #2542 题意:给一棵不超过$ 18$个节点的树,$ 5000 ...

  3. loj#2542. 「PKUWC2018」随机游走(树形dp+Min-Max容斥)

    传送门 首先,关于\(Min-Max\)容斥 设\(S\)为一个点的集合,每个点的权值为走到这个点的期望时间,则\(Max(S)\)即为走遍这个集合所有点的期望时间,\(Min(S)\)即为第一次走到 ...

  4. loj#2542. 「PKUWC2018」随机游走(MinMax容斥 期望dp)

    题意 题目链接 Sol 考虑直接对询问的集合做MinMax容斥 设\(f[i][sta]\)表示从\(i\)到集合\(sta\)中任意一点的最小期望步数 按照树上高斯消元的套路,我们可以把转移写成\( ...

  5. 【LOJ】#2542. 「PKUWC2018」随机游走

    题解 虽然我知道minmax容斥,但是--神仙能想到把这个dp转化成一个一次函数啊= = 我们相当于求给定的\(S\)集合里最后一个被访问到的点的时间,对于这样的max的问题,我们可以用容斥把它转化成 ...

  6. LOJ2542. 「PKUWC2018」随机游走

    LOJ2542. 「PKUWC2018」随机游走 https://loj.ac/problem/2542 分析: 为了学习最值反演而做的这道题~ \(max{S}=\sum\limits_{T\sub ...

  7. 「PKUWC2018」随机游走(min-max容斥+FWT)

    「PKUWC2018」随机游走(min-max容斥+FWT) 以后题目都换成这种「」形式啦,我觉得好看. 做过重返现世的应该看到就想到 \(min-max\) 容斥了吧. 没错,我是先学扩展形式再学特 ...

  8. loj2542 「PKUWC2018」随机游走 MinMax 容斥+树上高斯消元+状压 DP

    题目传送门 https://loj.ac/problem/2542 题解 肯定一眼 MinMax 容斥吧. 然后问题就转化为,给定一个集合 \(S\),问期望情况下多少步可以走到 \(S\) 中的点. ...

  9. 「PKUWC2018」随机游走

    题目 我暴力过啦 看到这样的东西我们先搬出来\(min-max\)容斥 我们设\(max(S)\)表示\(x\)到达点集\(S\)的期望最晚时间,也就是我们要求的答案了 显然我们也很难求出这个东西,但 ...

随机推荐

  1. 简话Angular 02 Angular控制器-作用域嵌套

    一句话: 就是孩子可以啃老,老子不能动孩子一根毛! * 子控制器有父控制器里变量的所有权限,可以读取,也可以修改. * 父控制器不能读,也不能修改孩子的变量 1. html代码 <div ng- ...

  2. PHP:第一章——PHP中常量和预定义常量

    <?php /*****************************************************/ //1.常量的定义 //常量:声明一次后长期不变的量,以字母或下划线开 ...

  3. jsonp 遍历文档

    遍历文档 将html解析成一个Document后,就可以使用类似Dom的方法进行操作 File input = new File("/tmp/input.html"); Docum ...

  4. 关于const的一些注意事项

    1.const对象必须初始化,一旦创建其值就无法更改 2.默认情况下,const对象仅在文件内有效,若想在多个文件中使用同一个const对象,就是不在每个文件独立的定义一个const对象,可以进行如下 ...

  5. Python 字符串的相关操作

    s = "abcdefg" s1 = s.capitalize() # 把首字母变成大写, 返回给你一个新的字符串 print(s) print(s1) s = "ale ...

  6. TouchJSON的简单使用

    TouchJSON是OC转换JSON的一个第三方类库,使用简单.在GitHub上可以轻松获取:TouchJSON 以下是简单的事例演示从douban movie请求JSON数据并转为字典对象后对控件赋 ...

  7. postman--安装及Interceptor插件

        1. 官网安装(看网速-我下载的时候一直下载失败) 打开官网,https://www.getpostman.com 选择ios或者win 2. 非官网安装 https://pan.baidu. ...

  8. vector类转换Mat类

    前言 一个个数据push back到vector之后,可以使用Mat()函数将vector类型转换为Mat类型. 在opencv中Mat类的构造函数中有一个构造函数可以直接把vector类转换为Mat ...

  9. opencv-python教程学习系列7-opencv图像基本操作

    前言 opencv-python教程学习系列记录学习python-opencv过程的点滴,本文主要介绍图像的基本操作,坚持学习,共同进步. 系列教程参照OpenCV-Python中文教程: 系统环境 ...

  10. Linux配置python和pip环境

    CentOS: 1.首先安装EPEL扩展源: yum install -y epel-release 2.系统自带python2,所以只需安装python3 yum install -y python ...