题解

虽然我知道minmax容斥,但是……神仙能想到把这个dp转化成一个一次函数啊= =

我们相当于求给定的\(S\)集合里最后一个被访问到的点的时间,对于这样的max的问题,我们可以用容斥把它转化成min问题

也就是

\(max{S} = \sum_{T \subset S} (-1)^{|T| + 1}min{T}\)

然后我们变成要求对给定的集合,最早访问到其中的点的期望

设当前的点集为\(S\),\(f(u)\)为从u点出发最早到\(S\)中的点期望的步数

如果\(u \in S\)

\(f(u) = 0\)

否则

\(f(u) = \frac{1}{d[u]}(f(fa[u]) + 1)+ \frac{1}{d[u]}\sum (f(ch[u]) + 1)\)

我们发现,从叶子节点开始倒推,我们每个点都可以表示成

\(f(u) = A_u f(fa[u]) + B_u\)的式子

那么我们把这个式子代进去

设\(v\)代表\(u\)的儿子

\((1 - \frac{\sum A_{v}}{d[u]})f(u) = \frac{1}{d[u]}f(fa[u]) + (1 + \frac{\sum B_{v}}{d[u]})\)

从叶子开始倒退即可,我们把起点当根,那么答案就是起点的\(B_x\)

最后用FMT累加起来可以做到\(O(1)\)回答询问(也可以子集枚举累加)

复杂度\(O(n 2^n + Q)\)

代码

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <set>
#include <cmath>
#include <bitset>
#define enter putchar('\n')
#define space putchar(' ')
//#define ivorysi
#define pb push_back
#define MAXN 100005
#define mo 974711
#define pii pair<int,int>
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 - '0' + c;
c = getchar();
}
res = res * f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) out(x / 10);
putchar('0' + x % 10);
}
const int MOD = 998244353;
int N,Q,st,A[25],B[25],D[25],cnt,f[(1 << 18) + 5],inv[20];
int inc(int a,int b) {
return a + b >= MOD ? a + b - MOD : a + b;
}
int mul(int a,int b) {
return 1LL * a * b % MOD;
}
int fpow(int x,int c) {
int t = x,res = 1;
while(c) {
if(c & 1) res = mul(res,t);
t = mul(t,t);
c >>= 1;
}
return res;
}
struct node {
int to,next;
}E[105];
int head[20],sumE;
void add(int u,int v) {
E[++sumE].to = v;
E[sumE].next = head[u];
head[u] = sumE;
}
void dp(int u,int fa,int S) {
if(S >> (u - 1) & 1) {++cnt;}
A[u] = B[u] = 0;
int SumA = 0,SumB = 0;
for(int i = head[u] ; i ; i = E[i].next) {
int v = E[i].to;
if(v != fa) {
dp(v,u,S);
SumA = inc(SumA,A[v]);
SumB = inc(SumB,B[v]);
}
}
if(S >> (u - 1) & 1) return;
int m = inc(1,MOD - mul(SumA,inv[D[u]]));
m = fpow(m,MOD - 2);
int k = inc(1,mul(SumB,inv[D[u]]));
A[u] = mul(inv[D[u]],m);
B[u] = mul(k,m);
}
void Solve() {
read(N);read(Q);read(st);
int u,v;
for(int i = 1 ; i < N ; ++i) {
read(u);read(v);
add(u,v);add(v,u);
++D[u];++D[v];
}
inv[1] = 1;
for(int i = 2 ; i <= N ; ++i) {
inv[i] = mul(inv[MOD % i],(MOD - MOD / i));
}
for(int S = 1 ; S < (1 << N) ; ++S) {
cnt = 0;
dp(st,0,S);
if((cnt + 1) & 1) f[S] = MOD - B[st];
else f[S] = B[st];
out(f[S]);space;
}
enter;
for(int i = 1 ; i < (1 << N) ; i <<= 1) {
for(int j = 1 ; j < (1 << N) ; ++j) {
if(j & i) f[j] = inc(f[j],f[j ^ i]);
}
}
int k,S;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Solve();
}

颓颓颓颓颓

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

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

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

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

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

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

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

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

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

  5. loj#2542. 「PKUWC2018」随机游走(MinMax容斥 期望dp)

    题意 题目链接 Sol 考虑直接对询问的集合做MinMax容斥 设\(f[i][sta]\)表示从\(i\)到集合\(sta\)中任意一点的最小期望步数 按照树上高斯消元的套路,我们可以把转移写成\( ...

  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. 数据分析与展示---Numpy数据存取与函数

    简介 一:数据的CSV文件存取(一维或二维) (一)写入文件savetxt (二)读取文件loadtxt 二:多维数据的存取 (一)保存文件tofile (二)读取文件fromfile (三)NumP ...

  2. 蓝桥杯 地宫寻宝 DFS 动态规划

    #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <cstdio> #include <cstdl ...

  3. 程序员 & 设计师都能用上的 75 份速查手册

    分享75份开发人员和设计师会用到的速查手册,由 vikas 收集整理,包括:jQuery.HTML.HTML5.CSS.CSS3.JavaScript.Photoshop .git.Linux.Jav ...

  4. Linux系统接入小区宽带

    jollywing(jollywing@foxmail.com) 安装 rp-pppoe 今天去联通营业厅开通了家庭宽带,回到家就搜索怎么用Linux接入小区宽带,发现大多数人都选择用PPPOE拨号上 ...

  5. Android 动态添加线性布局(.java文件内) 实现控件按比例分割空间

    这里实现 两个 编辑框同一水平上 按1:1分割空间 这里的1:1 比例可以通过 lp1.weight :  1p2.weight  =m:n 实现 { LinearLayout l=new Linea ...

  6. 微服务深入浅出(9)-- Nginx

    Nginx ("engine x") 是一个高性能的HTTP和反向代理服务器,处理请求是异步非阻塞的,多个连接(万级别)可以对应一个进程.而Apache是同步多进程模型,一个连接对 ...

  7. webrtc前景如何

    首先WebRTC是什么? WebRTC --- Web browsers with Real-Time Communications (RTC). WebRTC是一个免费.开放的项目.使web浏览器通 ...

  8. 企业日志大数据分析系统ELK+KAFKA实现【转】

    背景: 最近线上上了ELK,但是只用了一台Redis在中间作为消息队列,以减轻前端es集群的压力,Redis的集群解决方案暂时没有接触过,并且Redis作为消息队列并不是它的强项:所以最近将Redis ...

  9. javascript按照指定格式获取上一个月的日期

    //get pre month//get pre month function getPreMonth() { var date=new Date().Format("yyyy-MM-dd& ...

  10. C# 执行固定个数任务自行控制进入线程池的线程数量,多任务同时但是并发数据限定

    思路来源:http://bbs.csdn.NET/topics/390819824,引用该页面某网友提供的方法. 题目:我现在有100个任务,需要多线程去完成,但是要限定同时并发数量不能超过5个. 原 ...