Description

给定一棵 \(n\) 个结点的树,你从点 \(x\) 出发,每次等概率随机选择一条与所在点相邻的边走过去。

有 \(Q\) 次询问,每次询问给定一个集合 \(S\),求如果从 \(x\) 出发一直随机游走,直到点集 \(S\) 中所有点都至少经过一次的话,期望游走几步。

特别地,点 \(x\)(即起点)视为一开始就被经过了一次。

答案对 $998244353 $ 取模。

Solution

考虑 min-max 容斥,问题变成求从 \(x\) 点出发第一次到集合 \(S\) 中的点的期望步数

枚举集合 \(S\),尝试树形DP求出

设 \(f(i,S)\) 表示从点 \(i\) 出发第一次到达集合 \(S\) 中的点的期望步数

则有转移 \(f(i,S)=1+\frac1{deg(i)}\cdot f(fa[i],S)+\frac1{deg(i)}\sum\limits_{son}f(son,S)\)

根据我从没见过的树形DP常见套路,\(f(i)\) 一般都可以写成 \(A\cdot f(fa)+B\) 的形式

然后推式子

\[f(i,S)=1+\frac1{deg(i)}\cdot f(fa[i],S)+\frac1{deg(i)}(\sum\limits_{son}A(son)\cdot f(x)+B(son))
\]

\[f(i,S)=\frac1{deg(i)-\sum\limits_{son}A(son)}\cdot f(fa[i],S)+\frac{deg(i)+\sum\limits_{son}B(son)}{deg(x)-\sum\limits_{son}A(son)}
\]

得:\(A(i)=\frac1{deg(i)-\sum\limits_{son}A(son)},B(i)=\frac{deg(i)+\sum\limits_{son}B(son)}{deg(x)-\sum\limits_{son}A(son)}\)

当DP到一个 \(S\) 集合中的节点 \(p\) 时,令 \(A(p)=B(p)=0\),表示从这个点出发期望走 \(0\) 步就可以到达集合 \(S\) 中的点。最后的 \(B(x)\) 就是答案(因为 \(f(fa[x])\) 始终为 \(0\) )

Code

#include<bits/stdc++.h>
using std::min;
using std::max;
using std::swap;
using std::vector;
typedef double db;
typedef long long ll;
#define pb(A) push_back(A)
#define pii std::pair<int,int>
#define all(A) A.begin(),A.end()
#define mp(A,B) std::make_pair(A,B)
#define int long long
const int N=19;
const int mod=998244353; int a[N],b[N],f[1<<N],cnts[1<<N];
int n,q,s,cnt,maxn,head[N],deg[N]; struct Edge{
int to,nxt;
}edge[N<<1]; void add(int x,int y){
edge[++cnt].to=y;
edge[cnt].nxt=head[x];
head[x]=cnt;
} int ksm(int a,int b=mod-2,int ans=1){
while(b){
if(b&1) ans=ans*a%mod;
a=a*a%mod;b>>=1;
} return ans;
} void dfs(int now,int fa,int S){
if(S>>now-1&1) return a[now]=b[now]=0,void();
for(int i=head[now];i;i=edge[i].nxt){
int to=edge[i].to;
if(to==fa) continue;
dfs(to,now,S);
(a[now]+=a[to])%=mod;(b[now]+=b[to])%=mod;
} a[now]=ksm((deg[now]-a[now]+mod)%mod);b[now]=(b[now]+deg[now])%mod*a[now]%mod;
} int getint(){
int X=0,w=0;char ch=getchar();
while(!isdigit(ch))w|=ch=='-',ch=getchar();
while( isdigit(ch))X=X*10+ch-48,ch=getchar();
if(w) return -X;return X;
} signed main(){
n=getint(),q=getint(),s=getint();maxn=1<<n;
for(int i=1;i<n;i++){
int x=getint(),y=getint();
add(x,y),add(y,x);deg[x]++;deg[y]++;
}
for(int i=1;i<maxn;i++){
cnts[i]=cnts[i>>1]+(i&1);
memset(a,0,sizeof a),memset(b,0,sizeof b);
dfs(s,0,i);
f[i]=(cnts[i]&1?b[s]:mod-b[s]);
}
for(int i=1;i<=n;i++)
for(int j=1;j<maxn;j++)
if(j>>i-1&1) (f[j]+=f[j^(1<<i-1)])%=mod;
while(q--){
int len=getint(),x=0;
while(len--) x|=1<<getint();
printf("%lld\n",f[x>>1]);
} return 0;
}

[PKUWC2018] 随机游走的更多相关文章

  1. 【LOJ#2542】[PKUWC2018]随机游走(min-max容斥,动态规划)

    [LOJ#2542][PKUWC2018]随机游走(min-max容斥,动态规划) 题面 LOJ 题解 很明显,要求的东西可以很容易的进行\(min-max\)容斥,那么转为求集合的\(min\). ...

  2. LOJ2542 PKUWC2018 随机游走 min-max容斥、树上高斯消元、高维前缀和、期望

    传送门 那么除了D1T3,PKUWC2018就更完了(斗地主这种全场0分的题怎么会做啊) 发现我们要求的是所有点中到达时间的最大值的期望,\(n\)又很小,考虑min-max容斥 那么我们要求从\(x ...

  3. [LOJ#2542] [PKUWC2018] 随机游走

    题目描述 给定一棵 n 个结点的树,你从点 x 出发,每次等概率随机选择一条与所在点相邻的边走过去. 有 Q 次询问,每次询问给定一个集合 S,求如果从 x 出发一直随机游走,直到点集 S 中所有点都 ...

  4. LOJ #2542 [PKUWC2018]随机游走 (概率期望、组合数学、子集和变换、Min-Max容斥)

    很好很有趣很神仙的题! 题目链接: https://loj.ac/problem/2542 题意: 请自行阅读 题解首先我们显然要求的是几个随机变量的最大值的期望(不是期望的最大值),然后这玩意很难求 ...

  5. 【洛谷5643】[PKUWC2018] 随机游走(Min-Max容斥+待定系数法+高维前缀和)

    点此看题面 大致题意: 从一个给定点出发,在一棵树上随机游走,对于相邻的每个点均有\(\frac 1{deg}\)的概率前往.多组询问,每次给出一个点集,求期望经过多少步能够访问过点集内所有点至少一次 ...

  6. 洛谷 P5643 - [PKUWC2018]随机游走(Min-Max 容斥+FWT+树上高斯消元,hot tea)

    题面传送门 一道挺综合的 hot tea,放到 PKUWC 的 D2T2 还挺喜闻乐见的( 首先我们考虑怎样对一个固定的集合 \(S\) 计算答案,注意到我们要求的是一个形如 \(E(\max(S)) ...

  7. 题解-PKUWC2018 随机游走

    Problem loj2542 题意:一棵 \(n\) 个结点的树,从点 \(x\) 出发,每次等概率随机选择一条与所在点相邻的边走过去,询问走完一个集合 \(S\)的期望时间,多组询问 \(n\le ...

  8. LOJ2542 PKUWC2018随机游走(概率期望+容斥原理)

    如果直接dp,状态里肯定要带上已走过的点的集合,感觉上不太好做. 考虑一种对期望的minmax容斥:其中Max(S)为遍历完S集合的期望步数,Min(S)为遍历到S集合中一个点的期望步数.当然才不管怎 ...

  9. [LOJ2542][PKUWC2018]随机游走(MinMax容斥+树形DP)

    MinMax容斥将问题转化为求x到S中任意点的最小时间. 树形DP,直接求概率比较困难,考虑只求系数.最后由于x节点作为树根无父亲,所以求出的第二个系数就是答案. https://blog.csdn. ...

随机推荐

  1. iBtais 多重嵌套循环

    iBatis支持集合循环, 但是如何做到双重循环, 请见下例子 例子描述: 需要去三张结构相同的表中获取信息, 需要将信息拼合去重后返回 入参数据类型: Map<String,Object> ...

  2. uboot常用的函数

    http://blog.csdn.net/ooonebook/article/details/53206623 以下例子都以project X项目tiny210(s5pv210平台,armv7架构)为 ...

  3. fiddler抓包工具总结

    Fiddler 抓包工具总结 Fiddler是一个蛮好用的抓包工具,可以将网络传输发送与接受的数据包进行截获.重发.编辑.转存等操作.也可以用来检测网络安全.反正好处多多,举之不尽呀!当年学习的时候也 ...

  4. 文本超过控件长度自动显示省略号的css

    overflow: hidden; white-space: nowrap; text-overflow: ellipsis;

  5. POJ2947-Widget Factory

    工厂里每件期间的生产时间为3-9天,告诉你有N个器件和M个计划,每个计划都是说明生产1-N号器件的时间,最后问你每件器件的生产时间.或者多解或没有解. 例如样例 2 3 2 MON THU 1 2 3 ...

  6. 学习Python第七天

    进制拾遗: 二进制:01 八进制:01234567 十进制:0123456789 十六进制:0123456789ABCDEF 十进制转换八,十六进制语法 oct()八进制 关于8进制是逢8进一位的,我 ...

  7. IntelliJ IDEA小问题通过操作软件解决

    Diamond types are not supported at this language level http://blog.csdn.net/qq_34884729/article/deta ...

  8. 《HTTP权威指南》5-Web服务器

    各种形状,风格,尺寸的Web服务器 Web服务器会对HTTP请求进行处理并提供响应.Web服务器有着不同的风格,形状和尺寸但是不管功能,外貌,风格有何差异,所有的Web服务器都能够接收请求资源的HTT ...

  9. shiro与项目集成开发

    shiro与spring web项目开发 加入shiro的jar包 自定义realm /** * 自定义realm 继承授权realm * @author Administrator * */ pub ...

  10. 本周对于java中lamdba表达式与内部进行了学习 ,以下是我在学习就中遇到的问题

    在java中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类.我觉得其实就是类的嵌套,在一个类中再定义一个类,这里已成员内部类为讲,内部类可以自由地运用外部类定义的方法,但外部类想 ...