Loj #2542. 「PKUWC2018」随机游走

题目描述

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

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

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

答案对 $998244353 $ 取模。

输入格式

第一行三个正整数 \(n,Q,x\)。

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

接下来 \(Q\) 行,每行第一个数 \(k\) 表示集合大小,接下来 \(k\) 个互不相同的数表示集合 \(S\)。

输出格式

输出 \(Q\) 行,每行一个非负整数表示答案。

数据范围与提示

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

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

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

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

对于 \(100\%\) 的数据,有 \(1\leq n\leq 18\),\(1\leq Q\leq 5000\),\(1\leq k\leq n\)。

Orz

首先根据\(\min-\max\) 反演我们知道:

\[\max(S)=\sum_{T\subseteq S}(-1)^{|T|-1}\min(T)
\]

设\(f_{v,S}\)表示从\(v\)出发,经过\(S\)中至少一个节点的期望步数。

如果\(v\in S\),\(f_{v,S}=0\),否则:

\[f_v=1+\frac{1}{d_v}f_{fa}+\frac{1}{d_v}\sum f(u)\\
\]

然后这是颗树,我们可以将\(DP\)方程移项变成只与\(fa\)的\(f\)值个一个常数有关。

设:

\[f(v)=A_v*f_{fa}+B_v\\
\]

带回去化简:

\[f_v=1+\frac{1}{d_v}f_{fa}+\frac{1}{d_v}\sum (A_u*f_v+B_u)\\
(d_v-\sum A_u)*f_v=d_v+f_{fa}+\sum B_u\\
f_v=\frac{1}{d_v-\sum A_u}*f_{fa}+\frac{d_v+\sum B_u}{d_v-\sum A_u}
\]

得到:

\[A_v=\frac{1}{d_v-\sum A_u},B_v=\frac{d_v+\sum B_u}{d_v-\sum A_u}
\]

代码:

#include<bits/stdc++.h>
#define ll long long
#define N 19 using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;} const ll mod=998244353;
ll ksm(ll t,ll x) {
ll ans=1;
for(;x;x>>=1,t=t*t%mod)
if(x&1) ans=ans*t%mod;
return ans;
} int n;
int X,m;
struct road {int to,nxt;}s[N<<1];
int h[N],cnt;
void add(int i,int j) {s[++cnt]=(road) {j,h[i]};h[i]=cnt;} ll w[N];
int d[N];
ll A[N],B[N],f[N];
int tag[N]; void dfs(int v,int fa) {
A[v]=B[v]=0;
ll sumA=0,sumB=0;
for(int i=h[v];i;i=s[i].nxt) {
int to=s[i].to;
if(to==fa) continue ;
dfs(to,v);
sumA=(sumA+A[to])%mod;
sumB=(sumB+B[to])%mod;
}
if(tag[v]) A[v]=B[v]=0;
else A[v]=ksm(d[v]-sumA+mod,mod-2),B[v]=(d[v]+sumB)*ksm(d[v]-sumA+mod,mod-2)%mod;
} void dfs2(int v,int fa) {
f[v]=(A[v]*f[fa]+B[v])%mod;
for(int i=h[v];i;i=s[i].nxt) {
int to=s[i].to;
if(to==fa) continue ;
dfs2(to,v);
}
}
int mn[1<<N];
int main() {
n=Get(),m=Get(),X=Get();
int a,b;
for(int i=1;i<n;i++) {
a=Get(),b=Get();
add(a,b),add(b,a);
d[a]++,d[b]++;
}
for(int S=1;S<1<<n;S++) {
for(int i=1;i<=n;i++) if(S>>i-1&1) tag[i]=1;
dfs(1,0),dfs2(1,0);
mn[S]=f[X];
for(int i=1;i<=n;i++) if(S>>i-1&1) tag[i]=0;
}
for(int S=1;S<1<<n;S++) {
int cnt=0;
for(int i=0;i<n;i++) cnt+=S>>i&1;
if(!(cnt&1)) mn[S]=(mod-mn[S])%mod;
}
for(int i=0;i<n;i++) {
for(int S=1;S<1<<n;S++) {
if(S>>i&1) mn[S]=(mn[S]+mn[S^(1<<i)]+mod)%mod;
}
}
while(m--) {
int k=Get();
int sta=0;
while(k--) sta|=1<<Get()-1;
cout<<mn[sta]<<"\n";
}
return 0;
}

Loj #2542. 「PKUWC2018」随机游走的更多相关文章

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

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

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

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

  3. LOJ 2542 「PKUWC2018」随机游走 ——树上高斯消元(期望DP)+最值反演+fmt

    题目:https://loj.ac/problem/2542 可以最值反演.注意 min 不是独立地算从根走到每个点的最小值,在点集里取 min ,而是整体来看,“从根开始走到点集中的任意一个点就停下 ...

  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. 「PKUWC2018」随机游走

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

  9. loj2542「PKUWC2018」随机游走

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

随机推荐

  1. C语言中#undef作用

    #undef 作用:取消定义的宏 指令格式:#undef 标识符 1 #include <stdio.h> 2 3 #define MAX 5 4 5 int main() { 6 pri ...

  2. Node.js 事件循环机制

    Node.js 采用事件驱动和异步 I/O 的方式,实现了一个单线程.高并发的 JavaScript 运行时环境,而单线程就意味着同一时间只能做一件事,那么 Node.js 如何通过单线程来实现高并发 ...

  3. 深入介绍Java中的锁[原理、锁优化、CAS、AQS]

    1.为什么要用锁? 锁-是为了解决并发操作引起的脏读.数据不一致的问题. 2.锁实现的基本原理 2.1.volatile Java编程语言允许线程访问共享变量, 为了确保共享变量能被准确和一致地更新, ...

  4. shell if条件判断中:双中括号与单中括号的区别

    电脑重装了系统,登录虚拟机的shell脚本需重写,在为编写的脚本命名时发现存在同名脚本,才想起来是连接公司服务器的登录脚本,不想写俩脚本,怕记混了,那就整合一下.代码如下: #!/bin/bash#z ...

  5. 从壹开始前后端分离 [ vue + .netcore 补充教程 ] 二九║ Nuxt实战:异步实现数据双端渲染

    回顾 哈喽大家好!又是元气满满的周~~~二哈哈,不知道大家中秋节过的如何,马上又是国庆节了,博主我将通过三天的时间,给大家把项目二的数据添上(这里强调下,填充数据不是最重要的,最重要的是要配合着让大家 ...

  6. MyWebViewDemo【封装Webview常用配置和选择文件、打开相机、录音、打开本地相册的用法】

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 封装webview的常用配置和选择文件.打开相机.录音.打开本地相册的用法.[如果想要使用简单的预览功能,可以参考<MyBri ...

  7. django插入数据库错误:mysql的1267错误

    错误信息: django.db.utils.OperationalError: (1267, "Illegal mix of collations (latin1_swedish_ci,IM ...

  8. 从大数据技术变迁猜一猜AI人工智能的发展

    目前大数据已经成为了各家互联网公司的核心资产和竞争力了,其实不仅是互联网公司,包括传统企业也拥有大量的数据,也想把这些数据发挥出作用.在这种环境下,大数据技术的重要性和火爆程度相信没有人去怀疑. 而A ...

  9. 不使用 webpack,vuejs 异步加载模板

    webpack 打包不会玩,整了这么个小玩具 一段 vue 绑定代码,关键点在 gmallComponent 1.异步加载外部 vue 文件(非 .vue) 2.按一定规则拆分 template.sc ...

  10. jquery快速入门(四)

    jQuery 遍历 向上遍历 DOM 树 parent() parent() 方法返回被选元素的直接父元素.该方法只会向上一级对 DOM 树进行遍历. parents() parents() 方法返回 ...