题目描述

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

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

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

答案对 998244353998244353 取模。

输入格式

第一行三个正整数 n,Q,xn,Q,x。

接下来 n-1n−1 行,每行两个正整数 (u,v)(u,v) 描述一条树边。

接下来 QQ 行,每行第一个数 kk 表示集合大小,接下来 kk 个互不相同的数表示集合 SS。

输出格式

输出 QQ 行,每行一个非负整数表示答案。

数据范围与提示

对于 20\%20% 的数据,有 1\leq n,Q\leq 51≤n,Q≤5。

另有 10\%10% 的数据,满足给定的树是一条链。

另有 10\%10% 的数据,满足对于所有询问有 k=1k=1。

另有 30\%30% 的数据,满足 1\leq n\leq 10 ,Q=11≤n≤10,Q=1。

对于 100\%100% 的数据,有 1\leq n\leq 181≤n≤18,1\leq Q\leq 50001≤Q≤5000,1\leq k\leq n1≤k≤n。

  • 题解:

    • 单点询问可以用高斯消元;
    • 这个做法直接扩展到集合的话可以求出到$S$中任意一个点的期望步数;
    • 如果对于一种状态,记录$S$中每个点被走到的步数$t$;
    • 那么$S$中每个点都走到就是$t$的最大值,而刚刚求出来的是$t$的最小值;
    • 套用最值反演:$max{S} = \sum_{T \subseteq S ,T \neq \emptyset }  (-1)^{|T|-1} min{T}$;
    • 现在只需要快速求出到$S$中任意一个点的期望步数,设$f_{u}$为$u$到$S$的期望步数:
    • 可以得到:
    • $f_{u} = \frac{1}{d_{u}}  \sum_{v} f_{v} + 1 $
    • 这里$v$表示和$u$相邻的点;
    • 由于是一颗树,单独考虑父亲;
    • $f_{u} = \frac{1}{d_{u}} f_{fa} + \frac{1}{d_{u}} \sum_{v}f_{v} + 1$ ①
    • 这里$v$表示$u$的儿子节点;
    • 假设已经处理好了$u$的儿子,为了能够递推,将式子写成:
    • $f_{u} = A_{u}f_{fa} + B_{u}$ ②
    • 那么$A_{v}$和$B_{v}$是已经处理好的,对①中的$v$用②,再对比化简的①和②:
    • $$f_{u} = \frac{1}{d_{u} - \sum_{v}A_{v} } f_{fa} + \frac{d_{u} + \sum_{v}B_{v} }{d_{u} - \sum_{v} A_{v}}$$
    • 这样就可以$O(n)$递推$AB$
    • 用$fmt$处理反演部分的话,复杂度就是:$O(n2^n \ + \ q )$;
  •  #include<bits/stdc++.h>
    #define mod 998244353
    using namespace std;
    const int N=,M=;
    int n,q,s,S,num[<<],f[<<],o=,hd[N],A[N],B[N],d[N],inv[M];
    struct Edge{int v,nt;}E[N<<];
    void adde(int u,int v){
    E[o]=(Edge){v,hd[u]};hd[u]=o++;
    E[o]=(Edge){u,hd[v]};hd[v]=o++;
    }
    inline int Inv(int x){return x<1e5?inv[x]:1ll*(mod-mod/x)*Inv(mod%x)%mod;}
    void dfs(int u,int fa){
    if(S&<<(u-)){A[u]=B[u]=;return;}
    int s1=,s2=;
    for(int i=hd[u];i;i=E[i].nt){
    int v=E[i].v;
    if(v==fa)continue;
    dfs(v,u);
    s1=(s1+A[v])%mod,s2=(s2+B[v])%mod;
    }
    A[u]=Inv((d[u]-s1+mod)%mod);
    B[u]=1ll*A[u]*(s2+d[u])%mod;
    }
    int main(){
    #ifndef ONLINE_JUDGE
    freopen("loj2542.in","r",stdin);
    freopen("loj2542.out","w",stdout);
    #endif
    scanf("%d%d%d",&n,&q,&s);
    inv[]=;
    for(int i=;i<=1e5;++i)inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
    for(int i=,u,v;i<n;++i){
    scanf("%d%d",&u,&v);
    adde(u,v);
    d[u]++,d[v]++;
    }
    for(int i=;i<<<n;++i){
    S=i;dfs(s,);
    num[i]=num[i>>]+(i&);
    f[i]=(num[i]&)?B[s]:(mod-B[s])%mod;
    }
    for(int i=;i<n;++i)
    for(int j=<<i;j<<<n;++j){
    if(j>>i&)f[j]=(f[j]+f[j^(<<i)])%mod;
    }
    for(int i=,k;i<=q;++i){
    scanf("%d",&k);
    S=;for(int j=,x;j<=k;++j)scanf("%d",&x),S^=<<(x-);
    printf("%d\n",f[S]);
    }
    return ;
    }

loj2542「PKUWC2018」随机游走的更多相关文章

  1. LOJ2542. 「PKUWC2018」随机游走

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

  2. loj2542 「PKUWC2018」随机游走 【树形dp + 状压dp + 数学】

    题目链接 loj2542 题解 设\(f[i][S]\)表示从\(i\)节点出发,走完\(S\)集合中的点的期望步数 记\(de[i]\)为\(i\)的度数,\(E\)为边集,我们很容易写出状态转移方 ...

  3. LOJ2542. 「PKUWC2018」随机游走【概率期望DP+Min-Max容斥(最值反演)】

    题面 思路 我们可以把到每个点的期望步数算出来取max?但是直接算显然是不行的 那就可以用Min-Max来容斥一下 设\(g_{s}\)是从x到s中任意一个点的最小步数 设\(f_{s}\)是从x到s ...

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

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

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

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

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

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

  7. 【LOJ2542】「PKUWC2018」随机游走

    题意 给定一棵 \(n\) 个结点的树,你从点 \(x\) 出发,每次等概率随机选择一条与所在点相邻的边走过去. 有 \(Q\) 次询问,每次询问给定一个集合 \(S\),求如果从 \(x\) 出发一 ...

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

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

  9. 「PKUWC2018」随机游走

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

随机推荐

  1. CentOS7安装VMware Tools

    安装依赖包 [root@localhost ~]# yum -y install perl gcc gcc-c++ make cmake kernel kernel-headers kernel-de ...

  2. ipcs命令详解

    基础命令学习目录首页 多进程间通信常用的技术手段包括共享内存.消息队列.信号量等等,Linux系统下自带的ipcs命令是一个极好的工具,可以帮助我们查看当前系统下以上三项的使用情况,从而利于定位多进程 ...

  3. java内存结构JVM——java内存模型JMM——java对象模型JOM

    JVM内存结构 Java代码是要运行在虚拟机上的,而虚拟机在执行Java程序的过程中会把所管理的内存划分为若干个不同的数据区域,这些区域都有各自的用途.其中有些区域随着虚拟机进程的启动而存在,而有些区 ...

  4. Daily Scrum (2015/10/28)

    昨天DEV们完成了一部分代码风格的修整.今晚在与其他组进行交流时我们发现我们的代码是需要在服务器上运行的,而且服务器是需要配置的,而且据说需要花一些时间.所以在编写代码之前PM提出我们应该先把服务器搭 ...

  5. Scrum Meeting 11.06

    成员 今日任务 明日计划 用时 徐越 学习ListView+simpleAdapter,actionBar.阅读并修改前端代码 继续修改前端代码.完善数据库 4h 赵庶宏  构建后端数据库,进行完善 ...

  6. class 3 求数组中的最大值(单元测试)

    1.问题引出: int Largest(int list[], int length) { int i,max; ; i < (length – ); i ++ ) { if(list[i] & ...

  7. 在onResume()中调用getIntent()得不到Extra的问题

    之前 想做activity间的传值,注意 不是 startActivityforResult的那种, 在启动了多层activity再次启动activity想进入到singleTask的MainActi ...

  8. 将通过<input type="file">上传的txt文件存储在localStorage,提取并构建File对象

    参考博文: JS 之Blob 对象类型 在本地存储localStorage中保存图片和文件 <input type="file" id="jobData" ...

  9. Week-2-作业1

    第一章 概论 1.什么是程序? 答:在学习软件工程导论前,我们已经学习了一些计算机语言和数据结构这样的课程,并深刻的知道“程序=数据结构+算法”,但在学习中还是会产生如书中1.1讲所提到的那些疑问,二 ...

  10. Good Time 冲刺 六

    一.今日完成任务情况 第六天 日期:2018.6.19 王怡镔:今天完善了页面,对部分不足进行改进. 于鑫宇:对界面进行完善. 胡雅馨:今天完成前端页面,并改善后端,完善项目. 黄 鹤:做完最后的打卡 ...