很好很有趣很神仙的题!

题目链接: https://loj.ac/problem/2542

题意: 请自行阅读

题解首先我们显然要求的是几个随机变量的最大值的期望(不是期望的最大值),然后这玩意很难求,根据Min-Max容斥化成最小值的期望来求。

Minn-max容斥是指\(\max(x_1,x_2,...,x_n)=\sum_{S\in \{1,2,...,n\} } (-1)^{|S|-1} \min_{i\in S}(x_i)\) (所有元素都是正整数,这个尽管式子本身和期望没关系但是经常是求期望的时候用它)

这个式子可以如此理解: 若把每个正整数\(x\)看作集合\({1,2,...,x}\)的话,则\(\max\)就是集合并,\(\min\)就是集合交,容斥原理直接推论

所以我们\(O(2^n)\)枚举每个关键点的子集,然后问题转化为: 按照同样的规则随机游走,走到任何一个关键点时即停,问期望步数

然后可以设\(dp[x]\)表示\(x\)节点作为起始点的期望步数

若\(x\)是关键点,\(dp[x]=0\), 否则\(dp[x]=\frac{1}{du[x]}\sum_{Edge(u,v)}{dp[v]}+1\) (\(du[]\)是度数)

然后我们就可以愉快地来个高斯消元\(O(2^nn^3)\)处理单个询问了。(能得多少分别问我,没试过……)

神仙之处在下面: \(O(n)\)求解树上高消

由于这是棵树,所以我们如果dfs的话,可以把\(dp[x]\)记成一个关于\(dp[fa]\) (\(fa\)是父亲)的一次函数,形如\(dp[x]=A_xdp[fa]+B_x\).

然后假设现在做到点\(u\)(非根)则$$dp[u]=\frac{dp[fa]+\sum_{v\in son(u)}{A_vdp[u]+B_v}}{du[u]}+1$$

\[(1-\frac{\sum_{v\in son(u)}{a_v}}{du[u]})dp[u]=\frac{dp[fa]}{du[u]}+(\frac{\sum_{v\in son(u)}B_v}{du[u]}+1)
\]

归纳易证,只要有特殊点(\(A=B=0\))的存在,等式左边\(dp[u]\)的系数恒大于\(0\), 因此除过去就完成了\(A\)和\(B\)的递推!

裸做时间复杂度\(O(2^nnq)\), 子集和变换(高维前缀和,又称FMT)可以做到\(O(2^nn)\)预处理\(O(1)\)查询

代码

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<utility>
#define llong long long
using namespace std; const int N = 18;
const int P = 998244353;
llong fact[(1<<N)+3],finv[(1<<N)+3];
struct Edge
{
int v,nxt;
} e[(N<<1)+3];
int cnt[(1<<N)+3];
llong f[(1<<N)+3];
int fe[N+3];
int fa[N+3];
int du[N+3];
int n,q,s,en; llong quickpow(llong x,llong y)
{
llong cur = x,ret = 1ll;
for(int i=0; y; i++)
{
if(y&(1ll<<i)) {y-=(1ll<<i); ret = ret*cur%P;}
cur = cur*cur%P;
}
return ret;
}
llong mulinv(llong x) {return quickpow(x,P-2);} void addedge(int u,int v)
{
du[u]++;
en++; e[en].v = v;
e[en].nxt = fe[u]; fe[u] = en;
} void dfs0(int u)
{
for(int i=fe[u]; i; i=e[i].nxt)
{
if(e[i].v==fa[u]) continue;
fa[e[i].v] = u;
dfs0(e[i].v);
}
} pair<llong,llong> dfs(int u,int sta)
{
// printf("dfs(%d)\n",u);
if(sta&(1<<u)) {return make_pair(0,0);}
pair<llong,llong> ret = make_pair(1,1);
if(u!=s && du[u]==1) return ret;
llong s1 = 0ll,s2 = 0ll;
for(int i=fe[u]; i; i=e[i].nxt)
{
if(e[i].v==fa[u]) continue;
pair<llong,llong> tmp = dfs(e[i].v,sta);
s1 = (s1+tmp.first)%P,s2 = (s2+tmp.second)%P;
}
ret.first = mulinv(du[u]-s1+P)%P; ret.second = ret.first*(s2+du[u])%P;
return ret;
} int main()
{
cnt[0] = 0; for(int i=1; i<(1<<N); i++) cnt[i] = cnt[i>>1]+(i&1);
scanf("%d%d%d",&n,&q,&s); s--;
for(int i=1; i<n; i++)
{
int x,y; scanf("%d%d",&x,&y); x--; y--;
addedge(x,y); addedge(y,x);
}
fa[s] = -1; dfs0(s);
for(int i=1; i<(1<<n); i++)
{
if(i&(1<<s)) {f[i] = 0ll; continue;}
pair<llong,llong> tmp = dfs(s,i);
f[i] = tmp.second;
if((cnt[i]&1)==0) {f[i] = P-f[i];}
}
for(int i=0; i<n; i++)
{
for(int j=0; j<(1<<n); j++)
{
if(j&(1<<i)) {f[j] = (f[j]+f[j^(1<<i)])%P;}
}
}
for(int i=1; i<=q; i++)
{
int n0; scanf("%d",&n0);
int u = 0; for(int j=1; j<=n0; j++) {int x; scanf("%d",&x); x--; u+=(1<<x);}
printf("%lld\n",f[u]);
}
return 0;
}

LOJ #2542 [PKUWC2018]随机游走 (概率期望、组合数学、子集和变换、Min-Max容斥)的更多相关文章

  1. [LOJ#2542] [PKUWC2018] 随机游走

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

  2. 【LOJ#2542】[PKUWC2018]随机游走(min-max容斥,动态规划)

    [LOJ#2542][PKUWC2018]随机游走(min-max容斥,动态规划) 题面 LOJ 题解 很明显,要求的东西可以很容易的进行\(min-max\)容斥,那么转为求集合的\(min\). ...

  3. LOJ2542 PKUWC2018 随机游走 min-max容斥、树上高斯消元、高维前缀和、期望

    传送门 那么除了D1T3,PKUWC2018就更完了(斗地主这种全场0分的题怎么会做啊) 发现我们要求的是所有点中到达时间的最大值的期望,\(n\)又很小,考虑min-max容斥 那么我们要求从\(x ...

  4. [PKUWC2018] 随机游走

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

  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. LOJ2542 PKUWC2018随机游走(概率期望+容斥原理)

    如果直接dp,状态里肯定要带上已走过的点的集合,感觉上不太好做. 考虑一种对期望的minmax容斥:其中Max(S)为遍历完S集合的期望步数,Min(S)为遍历到S集合中一个点的期望步数.当然才不管怎 ...

  8. 题解-PKUWC2018 随机游走

    Problem loj2542 题意:一棵 \(n\) 个结点的树,从点 \(x\) 出发,每次等概率随机选择一条与所在点相邻的边走过去,询问走完一个集合 \(S\)的期望时间,多组询问 \(n\le ...

  9. [LOJ2542][PKUWC2018]随机游走(MinMax容斥+树形DP)

    MinMax容斥将问题转化为求x到S中任意点的最小时间. 树形DP,直接求概率比较困难,考虑只求系数.最后由于x节点作为树根无父亲,所以求出的第二个系数就是答案. https://blog.csdn. ...

随机推荐

  1. URAL 1601. AntiCAPS (strings)

    1601. AntiCAPS Time limit: 0.5 second Memory limit: 64 MB The blonde Angela has a new whim: internet ...

  2. 操作系统: 二级文件夹文件系统的实现(c/c++语言)

    操作系统的一个课程设计,实现一个二级文件夹文件系统. 用disk.txt模拟磁盘,使用Help查看支持的命令及其操作方式,root为超级用户(写在disk.txt中) 文件的逻辑结构:流式文件. 物理 ...

  3. Thinkpad E450c进入BIOS

    重启系统,一直按F12,进入系统设置后,按tab进入App Menu选项卡,选择Setup按回车进入BIOS设置

  4. (Go)07.Go语言中strings和strconv包示例代码详解01

    1.strings使用 前缀和后缀 HasPrefix判断字符串s是否以prefix开头: 示例: package main import ( "fmt" "string ...

  5. Eqs(枚举+ hash)

    http://poj.org/problem?id=1840 题意:给出系数a1,a2,a3,a4,a5,求满足方程的解有多少组. 思路:有a1x13+ a2x23+ a3x33+ a4x43+ a5 ...

  6. Java同步容器总结

    <0>StringBuffer适用于多线程场景,StringBuilder适用于字符串拼接[堆栈封闭] `Vector`实现`List`接口,底层和`ArrayList`类似,但是`Vec ...

  7. RabbltMQ

    协议:AMQP协议  支持事务 端口号:默认端口5672 1.简单队列(simple queue) 一个生产者对应一个消费者 2.工作队列(work queue) 一个生产者对应多个消费者: 轮询分发 ...

  8. [BZOJ1041]圆上的整点

    嗯... 自己看视频讲解? >Click Here< #include<cstdio> #include<queue> #include<iostream&g ...

  9. 5.26 idea生成javadoc

  10. JS排序之快速排序

    JS排序之快速排序 一个数组中的数据,选择索引为(2/数组长度)的那个数据作为基数,数组中的其他数据与它对比,比它数值小的放在做数组,比它数值大的放在右数组,最后组合 左数组+基数+右数组,其中,左数 ...