前言

这是学习容斥过程中的一个比较裸的题了

题意简介

题目链接

题目大意

给出一棵nnn个点的树,给出树上的一个点xxx
现在进行QQQ次询问,每次询问一个点集,求从xxx点开始进行随机随机游走,第一次走遍这个点集的期望步数
(随机游走即每次等概率走到一个与自己相邻的点)

数据范围

1≤n≤18,1≤Q≤50001\le n\le18,1\le Q\le 50001≤n≤18,1≤Q≤5000

前置知识(最值反演 Min-Max容斥)

max{S}=∑T⊆S(−1)∣T∣+1min{T}max\{S\}=\sum_{T\subseteq S}(-1)^{|T|+1}min\{T\}max{S}=T⊆S∑​(−1)∣T∣+1min{T}
具体介绍可以看我的博客
介绍链接
这个式子套上期望依然成立

题解

所有点第一次期望访问的步数的集合SSS,max{S}max\{S\}max{S}就是每个点都被走过的期望步数,min{S}min\{S\}min{S}代表里任意一个点被第一次访问的期望时间
我们发现我们现在要求的就是max{S}max\{S\}max{S}
但是直接求不好求,所以用Min-Max容斥转化成求min{S}min\{S\}min{S}
我们可以预处理min{S}min\{S\}min{S},并且Θ(3n)\Theta(3^n)Θ(3n)枚举子集计算答案
那么现在就是考虑如何求min{S}min\{S\}min{S}
这个似乎我当时在考场上就推出来了
考虑对于一个集合SSS,设f(x)f(x)f(x)为从xxx点开始随机游第一次访问集合SSS的期望步数
然后分类讨论
若x∈Sx\in Sx∈S
f(x)=0f(x)=0f(x)=0
若x∉Sx\notin Sx∈/​S
f(x)=1+1dx∑edge(x,y)f(y)f(x)=1+\frac{1}{d_x}\sum_{edge(x,y)}f(y)f(x)=1+dx​1​edge(x,y)∑​f(y)
其中dxd_xdx​为xxx的度数,edge(x,y)edge(x,y)edge(x,y)代表x,yx,yx,y间有边
对于x∉Sx\notin Sx∈/​S的部分随便定一个根root∈Sroot\in Sroot∈S
我们发现对于xxx是叶子节点的情况:f(x)=f(fax)+1f(x)=f(fa_x)+1f(x)=f(fax​)+1
我们发现对于xxx是非子节点的情况:f(x)=1+1dx∑y=sonxf(y)+1dxf(fax)f(x)=1+\frac{1}{d_x}\sum_{y=son_x}f(y)+\frac{1}{d_x}f(fa_x)f(x)=1+dx​1​y=sonx​∑​f(y)+dx​1​f(fax​)
我们设一个节点xxx的答案为(a,b)(a,b)(a,b)代表:f(x)=a+bf(fax)f(x)=a+bf(fa_x)f(x)=a+bf(fax​)
我们发现,对于任何一个节点的答案(a,b)(a,b)(a,b),一定满足b≤1b\le 1b≤1(实数意义下)
(由于root∈Sroot\in Sroot∈S,所以不会有枚举的节点没有fafafa的情况)
所以对于非叶子节点的xxx,等号右侧的f(x)f(x)f(x)的系数一定小于111,一项即可算出当前的的答案(a,b)(a,b)(a,b)
算完答案(a,b)(a,b)(a,b)后,即可从根倒着推回去
非常方便
这样算出来复杂度是Θ(3n)\Theta(3^n)Θ(3n)的,需要卡常,我写了一波被卡成70
这个时候就需要优化瓶颈
发现是裸的FMT,写一发就好了
复杂度Θ(2nnlogn)\Theta(2^nnlogn)Θ(2nnlogn)

代码

#include<cstdio>
#include<cctype>
namespace fast_IO
{const int IN_LEN=10000000,OUT_LEN=10000000;char ibuf[IN_LEN],obuf[OUT_LEN],*ih=ibuf+IN_LEN,*oh=obuf,*lastin=ibuf+IN_LEN,*lastout=obuf+OUT_LEN-1;inline char getchar_(){return (ih==lastin)&&(lastin=(ih=ibuf)+fread(ibuf,1,IN_LEN,stdin),ih==lastin)?EOF:*ih++;}inline void putchar_(const char x){if(oh==lastout)fwrite(obuf,1,oh-obuf,stdout),oh=obuf;*oh++=x;}inline void flush(){fwrite(obuf,1,oh-obuf,stdout);}
}
using namespace fast_IO;
#define getchar() getchar_()
#define putchar(x) putchar_((x))
//#include<ctime>
#define rg register
typedef long long LL;
template <typename T> inline T max(const T a,const T b){return a>b?a:b;}
template <typename T> inline T min(const T a,const T b){return a<b?a:b;}
template <typename T> inline void mind(T&a,const T b){a=a<b?a:b;}
template <typename T> inline void maxd(T&a,const T b){a=a>b?a:b;}
template <typename T> inline T abs(const T a){return a>0?a:-a;}
template <typename T> inline void swap(T&a,T&b){T c=a;a=b;b=c;}
//template <typename T> inline void swap(T*a,T*b){T c=a;a=b;b=c;}
template <typename T> inline T gcd(const T a,const T b){if(!b)return a;return gcd(b,a%b);}
template <typename T> inline T lcm(const T a,const T b){return a/gcd(a,b)*b;}
template <typename T> inline T square(const T x){return x*x;};
template <typename T> inline void read(T&x)
{char cu=getchar();x=0;bool fla=0;while(!isdigit(cu)){if(cu=='-')fla=1;cu=getchar();}while(isdigit(cu))x=x*10+cu-'0',cu=getchar();if(fla)x=-x;
}
template <typename T> inline void printe(const T x)
{if(x>=10)printe(x/10);putchar(x%10+'0');
}
template <typename T> inline void print(const T x)
{if(x<0)putchar('-'),printe(-x);else printe(x);
}
const LL mod=998244353;
inline LL pow(LL x,LL y)
{LL res=1;for(;y;y>>=1,x=x*x%mod)if(y&1)res=res*x%mod;return res;
}
int n,q,x,k;
int bit[20],inv[20],d[20];
int head[20],nxt[40],tow[40],tmp;
inline void addb(const int u,const int v)
{tmp++;nxt[tmp]=head[u];head[u]=tmp;tow[tmp]=v;
}
int zt;
struct Ans
{int a,b;inline Ans operator +(const Ans&y)const{return (Ans){a+y.a,b+y.b};}
}Q[20];
LL ans[20];
void dfs1(const int u,const int fa)
{if(zt&bit[u]){for(rg int i=head[u];i;i=nxt[i]){const int v=tow[i];if(v==fa)continue;dfs1(v,u);}Q[u].a=Q[u].b=0;}else{const LL INV=inv[d[u]];Q[u]=(Ans){1,INV};LL xs=1;for(rg int i=head[u];i;i=nxt[i]){const int v=tow[i];if(v==fa)continue;dfs1(v,u);xs=(xs+mod-INV*Q[v].b%mod)%mod;Q[u].a=(Q[u].a+Q[v].a*INV)%mod;}const LL INTO=pow(xs,mod-2);Q[u].a=INTO*Q[u].a%mod;Q[u].b=INTO*Q[u].b%mod;}
}
void dfs2(const int u,const int fa)
{if(zt&bit[u]){ans[u]=0;for(rg int i=head[u];i;i=nxt[i]){const int v=tow[i];if(v==fa)continue;dfs2(v,u);}}else{ans[u]=(Q[u].a+ans[fa]*Q[u].b)%mod;for(rg int i=head[u];i;i=nxt[i]){const int v=tow[i];if(v==fa)continue;dfs2(v,u);}}
}
int res[524288];
int pc[524288];
int main()
{bit[1]=1;for(rg int i=2;i<=19;i++)bit[i]=bit[i-1]<<1;inv[1]=1;for(rg int i=2;i<=19;i++)inv[i]=(LL)(mod-mod/i)*inv[mod%i]%mod;read(n),read(q),read(x);for(rg int i=1;i<n;i++){int u,v;read(u),read(v);addb(u,v),addb(v,u);d[u]++,d[v]++;}for(zt=1;zt<bit[n+1];zt++){pc[zt]=pc[zt>>1]^(zt&1);for(rg int i=1;i<=n;i++)if(zt&bit[i]){dfs1(i,i);dfs2(i,i);break;}if(pc[zt]&1)res[zt]=ans[x];else res[zt]=(mod-ans[x])%mod;}for(rg int i=1;i<bit[n+1];i<<=1)for(rg int j=0;j<bit[n+1];j++)if(i&j)res[j]=(res[j]+res[j^i])%mod;while(q--){read(k),zt=0;while(k--)read(x),zt|=bit[x];print(res[zt]),putchar('\n');}return flush(),0;
}

不知为何分类讨论使得程序拉的特别长

总结

min-max容斥很重要,使得整题好做了很多
然后这算是FMT的应用吧,清真好题

最值反演[PKUWC2018][loj2542]随机游走相关推荐

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

    LOJ#2542. 「PKUWC2018」随机游走 题目描述 Solution 去过一个点集中所有节点的期望时间不好求,考虑min−maxmin-maxmin−max容斥,转化为求第一次到达某一个点集 ...

  2. 「PKUWC2018」随机游走

    Min-Max容斥真好用 LOJ #2542 题意:给一棵不超过1818个节点的树,50005000次询问,每次问从根随机游走走遍一个集合的期望步数 Solution: 考虑Min-Max容斥 有Ma ...

  3. 【PKUWC2018】随机游走【Min-Max容斥】【树形dp】【FWT】

    题意:给一棵nnn个点的无权树和xxx,qqq次询问,每次给定一个点集SSS,询问从xxx开始每次随机走一步,SSS中的每个点至少被经过一次的期望步数. n≤18,q≤5000n\leq 18,q\l ...

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

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

  5. 随机游走问题的神奇应用(二)

    变概率椭圆型方程的第一边值问题的随机游走求解 一.问题的提出 二.问题的分析 三.模型的推广 四.问题的求解 一.问题的提出 a(P)∂2u∂x2+b(P)∂2u∂y2+c(P)∂u∂x+d(P)∂u ...

  6. 推荐系统 - 3 - 协同过滤算法、随机游走算法

    本总结是是个人为防止遗忘而作,不得转载和商用. 本节的前置知识是我总结的"推荐系统 - 1.2". 协同过滤算法 基于用户行为的数据而设计的推荐算法被称为协同过滤算法(Collab ...

  7. loj#2542 [PKUWC2018]随机游走 (概率期望、组合数学、子集和变换、Min-Max容斥)

    loj#2542 [PKUWC2018]随机游走 (概率期望.组合数学.子集和变换.Min-Max容斥) 很好很有趣很神仙的题! 题目链接: https://loj.ac/problem/2542 题 ...

  8. LOJ #2542 [PKUWC2018]随机游走 (概率期望、组合数学、子集和变换、Min-Max容斥)

    很好很有趣很神仙的题! 题目链接: https://loj.ac/problem/2542 题意: 请自行阅读 题解首先我们显然要求的是几个随机变量的最大值的期望(不是期望的最大值),然后这玩意很难求 ...

  9. 重启随机游走算法(RWR:Random Walk with Restart)

    重启随机游走算法(RWR:Random Walk with Restart) 1 pagerank算法的基本原理 Pagerank算法是Google的网页排名算法,由拉里佩奇发明.其基本思想是民主表决 ...

最新文章

  1. Kinect for Windows V2 SDK+ VS2012 环境搭建
  2. 刻意练习:Python基础 -- Task06. 字典与集合
  3. C#软件设计——小话设计模式原则之:依赖倒置原则DIP
  4. 笔记-项目范围管理-指导与管理项目工作-控制质量-确认范围-结束项目或阶段...
  5. Nagios监控之8:利用mutt+msmtp实现邮件报警
  6. 精品教程--Android实战系列源码与教程
  7. word List 43
  8. java phaser用法_第3章Phaser的使用-(java并发编程核心方法与框架)
  9. 2015生命之旅---第二站长沙杭州
  10. 深度学习多模态融合_多模态深度学习:用深度学习的方式融合各种信息
  11. httpservletresponse 重定向浏览器不变的原因_正确区分火狐浏览器(Firefox)中国版和国际版amp;下载方法...
  12. Python3基本数据类型(一、数字类型)
  13. 计算机毕设项目论文介绍(Java智慧物业管理系统为例)
  14. GPS测量中的数据格式——RINEX格式说明
  15. 达梦数据库-Dmpython+xlrd实现excel表数据一键入库代码分享
  16. 手写文本 matlab 识别,手写汉字识别matlab
  17. 向量的数量积,向量积,混合积及应用
  18. 程序员需知的9个编程学习官网,建议收藏
  19. 20190608 JavaBean转jsonString时首字母大写的问题
  20. 2020风中劲草pdf电子版完整版 下载

热门文章

  1. FastDFS整合SpringBoot - 实现service
  2. OAuth2.0授权码认证流程介绍
  3. 角色操作-角色添加代码实现
  4. 定时任务四种实现方式
  5. Redis分布式锁原理解析
  6. mysql主机咋填_mysql数据库主机填什么
  7. 删除 CentOS Stream 8 开机多余引导项及等待时间
  8. Influxdb修改数据保留策略
  9. 13.1-13.3 设置更改root密码,连接MySQL,MySQL常用命令
  10. 《数据结构与抽象:Java语言描述(原书第4版)》一练习