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

  1. #include<bits/stdc++.h>
  2. using std::min;
  3. using std::max;
  4. using std::swap;
  5. using std::vector;
  6. typedef double db;
  7. typedef long long ll;
  8. #define pb(A) push_back(A)
  9. #define pii std::pair<int,int>
  10. #define all(A) A.begin(),A.end()
  11. #define mp(A,B) std::make_pair(A,B)
  12. #define int long long
  13. const int N=19;
  14. const int mod=998244353;
  15. int a[N],b[N],f[1<<N],cnts[1<<N];
  16. int n,q,s,cnt,maxn,head[N],deg[N];
  17. struct Edge{
  18. int to,nxt;
  19. }edge[N<<1];
  20. void add(int x,int y){
  21. edge[++cnt].to=y;
  22. edge[cnt].nxt=head[x];
  23. head[x]=cnt;
  24. }
  25. int ksm(int a,int b=mod-2,int ans=1){
  26. while(b){
  27. if(b&1) ans=ans*a%mod;
  28. a=a*a%mod;b>>=1;
  29. } return ans;
  30. }
  31. void dfs(int now,int fa,int S){
  32. if(S>>now-1&1) return a[now]=b[now]=0,void();
  33. for(int i=head[now];i;i=edge[i].nxt){
  34. int to=edge[i].to;
  35. if(to==fa) continue;
  36. dfs(to,now,S);
  37. (a[now]+=a[to])%=mod;(b[now]+=b[to])%=mod;
  38. } a[now]=ksm((deg[now]-a[now]+mod)%mod);b[now]=(b[now]+deg[now])%mod*a[now]%mod;
  39. }
  40. int getint(){
  41. int X=0,w=0;char ch=getchar();
  42. while(!isdigit(ch))w|=ch=='-',ch=getchar();
  43. while( isdigit(ch))X=X*10+ch-48,ch=getchar();
  44. if(w) return -X;return X;
  45. }
  46. signed main(){
  47. n=getint(),q=getint(),s=getint();maxn=1<<n;
  48. for(int i=1;i<n;i++){
  49. int x=getint(),y=getint();
  50. add(x,y),add(y,x);deg[x]++;deg[y]++;
  51. }
  52. for(int i=1;i<maxn;i++){
  53. cnts[i]=cnts[i>>1]+(i&1);
  54. memset(a,0,sizeof a),memset(b,0,sizeof b);
  55. dfs(s,0,i);
  56. f[i]=(cnts[i]&1?b[s]:mod-b[s]);
  57. }
  58. for(int i=1;i<=n;i++)
  59. for(int j=1;j<maxn;j++)
  60. if(j>>i-1&1) (f[j]+=f[j^(1<<i-1)])%=mod;
  61. while(q--){
  62. int len=getint(),x=0;
  63. while(len--) x|=1<<getint();
  64. printf("%lld\n",f[x>>1]);
  65. } return 0;
  66. }

[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. 浮点数运算结果不精确,以及用String来构造BigDecimal进行浮点数精确计算

    1.浮点数运算结果不精确 先看如下代码 System.out.println(1.0 - 0.8); System.out.println(0.2 + 0.1); System.out.println ...

  2. .NET默认一个客户端对同一个服务器地址同时只能建立2个TCP连接

    做一个客户端的测试小程序测试web service的并发处理.开始用async task做,不管创建多少个task,用netstat看同时只有两个tcp连接.以为是async task的问题,改用Ba ...

  3. OC内存管理、非ARC机制、MRR机制

    在Xcode里面,默认为ARC(auto reference counting),也就是自动内存管理机制,在这里我们要了解的是内存管理,肯定是不能让系统帮我们管理内存,我们需要将ARC关闭,首先在左边 ...

  4. springboot 不同环境切换不同的配置文件

    开发的流程是本地>测试>预发布>正式,所以不同的环境,肯定是不同的配置文件,所以我们需要针对不同的环境做不同的配置切换. 下面我们来说说 springboot 是怎么来切换的: 1. ...

  5. js-图片轮播(极简)

    <!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8" ...

  6. 28.实现 strStr() 函数

    28.实现 strStr() 函数 给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始).如果不存在, ...

  7. MySQL--Double Write

    ##=======================================##目前大部分服务器使用4K或512B来格式化磁盘,而Innodb存储引擎使用默认16K的数据页,在写入16KB数据页 ...

  8. 理解 Linux 的虚拟内存

    前言 前不久组内又有一次我比较期待的分享:”Linux 的虚拟内存”.是某天晚上加班时,我们讨论虚拟内存的概念时,leader 发现几位同事对虚拟内存认识不清后,特意给这位同学挑选的主题(笑). 我之 ...

  9. 初识vw和vh

     最近在项目里突然看到了一行css代码,height:100vh; 一时间有点蒙蔽 因为之前有听过这个css3新增单位,但没有去了解过. 那这个单位又跟px,rem,em,%有什么不同呢? 简述:   ...

  10. Python的基础语法(一)

    0. 前言 最近正在重新整理Python的基础知识,以便更好地学习新知识.这一部分主要是讲述Python基础语法的演示.下面的语法都是基于Python3的语法. 1. 注释 注释:Python的注释方 ...