1. 程式人生 > >【LOJ 2542】【PKUWC2018】 隨機遊走(最值反演 + 樹上期望dp)

【LOJ 2542】【PKUWC2018】 隨機遊走(最值反演 + 樹上期望dp)

情況下 ret 次方 情況 font 期望 起點 n) fine

哇我太菜啦555555

不妨欽定我們需要訪問的點集為$S$,在$S$已知的情況下,我們令$f(x) $表示從$x$走到點集$S$中任意一點的期望步數。

若$x∈S$,則顯然$f(x)=0$,否則$f[x]=\frac{1}{d[x]}\sum f[ch[x]]+1$。其中$d[x]$表示與$x$相連的節點個數,$ch[x]$為與$x$相連的節點。

然後就列出了$n$條式子,顯然是一個$n$元一次方程,可以考慮用高斯消元去求解,這樣時間復雜度是$O(n^32^{n})$,只能拿$60$分(然而我考場上是零分啊嗚嗚嗚)

我們考慮用些快速點的方法,考慮將$f[x]$化為$A_xf[fa[x]]+B_x$。其中$fa[x]$表示$x$的父親。

$f[x]=A_x[fa[x]]+B_x=\frac{1}{d[x]}\sum f[ch[x]]$

$f[x]=\frac{1}{d[x]}f[fa[x]]+\frac{1}{d[x]}(A_{ch[x]}f[x]+B_{ch[x]})+1$。

經過化簡後,得

$f[x]= \dfrac{f[fa[x]]+\sum B_{ch[x]}+1}{d[u]-\sum A_{ch[x]}}$

我們令$g[S]$表示從給定起點$X$出發,走到集合$S$中任意一個點的期望步數。

那麽顯然,$g[S]=f[X]$。求出所有狀態的期望的時間復雜度顯然為$O(n 2^n)$。

我們令$G[S]$表示從給定起點$X$出發,將集合$S$中每個點至少走一次的期望步數。

根據$min-max$容斥的相關內容,有

$G[S]=\sum_{i∈S}g[i]\times (-1)^{|i|+1}$

然後我們可以花$O(3^n)$枚舉子集,預處理出所有答案。

查詢的時候$O(1)$查詢即可。

完結撒花

 1 #include<bits/stdc++.h>
 2 #define M 18
 3 #define MOD 998244353
 4 #define L long long
 5 using namespace std;
 6 
 7 L pow_mod(L x,L k){
 8     L ans=1;
9 while(k){ 10 if(k&1) ans=ans*x%MOD; 11 x=x*x%MOD; k>>=1; 12 } 13 return ans; 14 } 15 16 L d[M]={0},invd[M]={0}; 17 struct edge{int u,next;}e[M<<1]={0}; int head[M]={0},use=0; 18 void add(int x,int y){use++;e[use].u=y;e[use].next=head[x];head[x]=use;} 19 20 L f[1<<M]={0},ans[1<<M]={0},zf[1<<M]={0},a[M]={0},b[M]={0}; int ok[1<<M]={0}; 21 22 int n,q,rt; 23 void dfs(int x,int fa,int S){ 24 if((1<<x)&S) return; 25 for(int i=head[x];i;i=e[i].next) 26 if(e[i].u!=fa){ 27 dfs(e[i].u,x,S); 28 b[x]+=b[e[i].u]; 29 a[x]+=a[e[i].u]; 30 } 31 b[x]%=MOD; a[x]%=MOD; 32 L inv=pow_mod((d[x]-a[x]+MOD)%MOD,MOD-2); 33 a[x]=inv; 34 b[x]=(b[x]*inv+inv*d[x])%MOD; 35 } 36 37 void solve(int x){ 38 ok[x]=1; 39 for(int i=x;i;i=x&(i-1)) 40 ans[x]+=zf[i]*f[i]; 41 ans[x]=(ans[x]%MOD+MOD)%MOD; 42 } 43 44 int main(){ 45 //freopen("a.out","w",stdout); 46 scanf("%d%d%d",&n,&q,&rt); rt--; 47 for(int i=1;i<n;i++){ 48 int x,y; scanf("%d%d",&x,&y); 49 x--; y--; add(x,y); add(y,x); 50 d[x]++; d[y]++; 51 } 52 for(int i=0;i<n;i++) invd[i]=pow_mod(d[i],MOD-2); 53 int hh=1<<n; 54 for(int i=1;i<hh;i++){ 55 memset(a,0,sizeof(a)); 56 memset(b,0,sizeof(b)); 57 dfs(rt,-1,i); 58 f[i]=b[rt]; zf[i]=-1; 59 for(int j=0;j<n;j++) 60 if((1<<j)&i) zf[i]=-zf[i]; 61 } 62 while(q--){ 63 int k,hh=0; scanf("%d",&k); 64 while(k--){ 65 int x; scanf("%d",&x); 66 hh+=1<<(x-1); 67 } 68 if(!ok[hh]) solve(hh); 69 printf("%lld\n",ans[hh]); 70 } 71 }

【LOJ 2542】【PKUWC2018】 隨機遊走(最值反演 + 樹上期望dp)