Description

题库链接

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

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

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

答案对 \(998244353\) 取模。

Solution

不妨设 \(f_{i,S}\) 表示在点 \(i\) 时,要遍历集合 \(S\) 的期望步数。那么对于一个询问 \(S\) ,答案就是 \(f_{x,S}\) 。

从两个方面来考虑如何求 \(f\) :

  1. 如果 \(u\not\in S\) ,由套路,显然满足 \[f_{u,S}=\frac{\sum_{\text{v is the neighbor of u}}f_{v,S}}{degree_u}+1\]
  2. 如果 \(u\in S\)
    1. 若 \(\{u\}=S\) ,显然 \(f_{u,S}=0\) ;
    2. 若 \(\{u\}\neq S\) ,容易得到 \(f_{u,S}=f_{u,S-\{u\}}\)

这样我们对于同一个状态 \(S\) 可以得到若干个方程,那么在这一个状态内高斯消元即可。

由于是树上消元,所以可以用[Codeforces 802L]Send the Fool Further! (hard)的方法化成 \(f_u=k_uf_{fa_u}+b_u\) 的形式 \(O(n)\) 求解。

总复杂度是 \(O(n\log(n)2^n+Q)\) ,其中 \(\log(n)\) 是求逆元的复杂度。

Code

#include <bits/stdc++.h>
using namespace std;
const int N = 20, SIZE = (1<<18)+5, yzh = 998244353; int n, q, x, u, v, bin[N], dg[N], S;
struct tt {int to, next; }edge[N<<1];
int path[N], top, k[N], b[N], f[N][SIZE]; int quick_pow(int a, int b) {
int ans = 1;
while (b) {
if (b&1) ans = 1ll*ans*a%yzh;
b >>= 1, a = 1ll*a*a%yzh;
}
return ans;
}
void dfs(int u, int fa) {
k[u] = b[u] = 0;
for (int i = path[u], v; i; i = edge[i].next)
if ((v = edge[i].to) != fa) dfs(v, u);
if (!(bin[u-1]&S)) {
if (dg[u] == 1 && x != u) k[u] = b[u] = 1;
else {
k[u] = dg[u], b[u] = dg[u];
for (int i = path[u], v; i; i = edge[i].next)
if ((v = edge[i].to) != fa) {
(k[u] -= k[v]) %= yzh; (b[u] += b[v]) %= yzh;
}
k[u] = quick_pow(k[u], yzh-2);
b[u] = 1ll*b[u]*k[u]%yzh;
}
}else {
if (S^bin[u-1]) {
k[u] = 0; b[u] = f[u][S^bin[u-1]];
}else k[u] = b[u] = 0;
}
}
void cal(int u, int fa) {
f[u][S] = (1ll*k[u]*f[fa][S]%yzh+b[u])%yzh;
for (int i = path[u], v; i; i = edge[i].next)
if ((v = edge[i].to) != fa) cal(v, u);
}
void add(int u, int v) {edge[++top] = (tt){v, path[u]}, path[u] = top; ++dg[v]; }
void work() {
scanf("%d%d%d", &n, &q, &x);
for (int i = 1; i < n; i++) {
scanf("%d%d", &u, &v);
add(u, v), add(v, u);
}
bin[0] = 1; for (int i = 1; i < N; i++) bin[i] = (bin[i-1]<<1);
for (int i = 1; i < bin[n]; i++) S = i, dfs(x, 0), cal(x, 0);
while (q--) {
S = 0; scanf("%d", &u);
for (int i = 1; i <= u; i++) scanf("%d", &v), S |= bin[v-1];
printf("%d\n", (f[x][S]+yzh)%yzh);
}
}
int main() {work(); return 0; }

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

  1. LOJ #2542. 「PKUWC 2018」随机游走(最值反演 + 树上期望dp + FMT)

    写在这道题前面 : 网上的一些题解都不讲那个系数是怎么推得真的不良心 TAT (不是每个人都有那么厉害啊 , 我好菜啊) 而且 LOJ 过的代码千篇一律 ... 那个系数根本看不出来是什么啊 TAT ...

  2. 【LOJ2542】【PKUWC 2018】随机游走 min-max容斥 树上高斯消元

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

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

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

  4. 「Luogu4321」随机游走

    「Luogu4321」随机游走 题目描述 有一张 \(n\) 个点 \(m\) 条边的无向图,\(Q\) 组询问,每次询问给出一个出发点和一个点集 \(S\) ,求从出发点出发随机游走走遍这个点集的期 ...

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

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

  6. 【Matlab】随机游走产生图像效果

    随机游走类似布朗运动,就是随机的向各个方向走吧.产生的图像实在漂亮,所以还是贴出分享. clear all; close all; clc; n=100000; x= 0; y= 0; pixel=z ...

  7. 介绍一个全局最优化的方法:随机游走算法(Random Walk)

    1. 关于全局最优化求解   全局最优化是一个非常复杂的问题,目前还没有一个通用的办法可以对任意复杂函数求解全局最优值.上一篇文章讲解了一个求解局部极小值的方法--梯度下降法.这种方法对于求解精度不高 ...

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

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

  9. [PKUWC2018] 随机游走

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

随机推荐

  1. Chapter6 胞内信号网络

    一.一条从细胞表面到细胞核的通路 二.Ras蛋白处于复杂信号级联的中心位置 胞外信号→酪氨酸激酶受体→Shc→Grb→Sos→Ras 三.酪氨酸的磷酸化控制着许多胞内信号蛋白的定位与活动 Src蛋白的 ...

  2. 前端vue框架 父组件与子组件之间的相互调用

    子组件调用父组件东西: 1.在父组件与子组件契合的标签的的template模板中绑定 v-bind:自定义一个名字=“要调用的名字” 2.在子组件的script中props:["自定义的名字 ...

  3. JavaScript使用注意事项

    1.jQuery和JS中页面加载完后执行方法的写法 (1)在javascript中用来执行页面加载中的操作时候,我们会使用 window.onload=function(){} window.onlo ...

  4. Swift5 语言指南(七) 集合类型

    Swift提供三种主要的集合类型,称为数组,集合和字典,用于存储值集合.数组是有序的值集合.集是唯一值的无序集合.字典是键值关联的无序集合. Swift中的数组,集合和字典总是清楚它们可以存储的值和键 ...

  5. 利用SSH反向隧道,连接内网服务器

    前言 公司有一台文件服务器(内部使用,无外网IP),上面主要安装了SVN服务,用来存储和共享各部门的文档,因为都是内网,直接远程(mstsc)上去就可以方便维护,但最近公司租了新的办公室,部分员工被分 ...

  6. Linux 环境下使用g++编译C++

    单个源文件生成可执行程序 下面是一个保存在文件 helloworld.cpp 中一个简单的 C++ 程序的代码: /* helloworld.cpp */ #include <iostream& ...

  7. Spring Boot核心配置

    启动类 在包根目录下添加启动类,必须包含main方法,再添加Spring Boot启动方法: SpringApplication.run(SampleController.class, args); ...

  8. 深度学习笔记(七)SSD 论文阅读笔记

    一. 算法概述 本文提出的SSD算法是一种直接预测目标类别和bounding box的多目标检测算法.与faster rcnn相比,该算法没有生成 proposal 的过程,这就极大提高了检测速度.针 ...

  9. 使用ES6的Promise完美解决回调地狱

    相信经常使用ajax的前端小伙伴,都会遇到这样的困境:一个接口的参数会需要使用另一个接口获取. 年轻的前端可能会用同步去解决(笑~),因为我也这么干过,但是极度影响性能和用户体验. 正常的前端会把接口 ...

  10. 机器学习与Tensorflow(6)——LSTM的Tensorflow实现、Tensorboard简单实现、CNN应用

    最近写的一些程序以及做的一个关于轴承故障诊断的程序 最近学习进度有些慢 而且马上假期 要去补习班 去赚下学期生活费 额.... 抓紧时间再多学习点 1.RNN递归神经网络Tensorflow实现程序 ...