[关闭]
@ysner 2018-08-13T09:58:13.000000Z 字数 2456 阅读 2010

[PKUWC2018]随机游走

容斥 DP 期望


题面

给定一棵个结点的树,你从点出发,每次等概率随机选择一条与所在点相邻的边走过去。
次询问,每次询问给定一个集合,求如果从出发一直随机游走,直到点集中所有点都至少经过一次的话,期望游走几步。
特别地,点(即起点)视为一开始就被经过了一次。

解析

咦??我会状压!
咦?所有点都至少经过一次?求期望?我会容斥!
以上为看题想法

还记得[HNOI2013]游走吧?
在那一道题中,由于转移具有后效性,我们只能用解方程来求出到每个点的概率。

但这里是一颗树!转移没有后效性。
于是可以像一般转移结果。
表示到达第一次到达号点的期望次数。
先列一个基本的期望转移式:(表示号点的度数,点的儿子)



根据套路,树上期望问题中,到点的期望次数可以表示为
依此继续化式子:




枚举所有,按上述式子转移。一旦遇到集合内的数,
这样就可得到所有的(在出发点)。

然后容斥就只要用个结论:


复杂度

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstdlib>
  4. #include<cstring>
  5. #include<cmath>
  6. #include<algorithm>
  7. #include<vector>
  8. #define re register
  9. #define il inline
  10. #define ll long long
  11. #define max(a,b) ((a)>(b)?(a):(b))
  12. #define min(a,b) ((a)<(b)?(a):(b))
  13. #define fp(i,a,b) for(re int i=a;i<=b;i++)
  14. #define fq(i,a,b) for(re int i=a;i>=b;i--)
  15. using namespace std;
  16. const int mod=998244353,N=20;
  17. struct Edge{int to,nxt;}e[N<<1];
  18. int n,Q,rt,h[N],cnt,a[N],k,mx,q[N],d[N];
  19. ll A[N],B[N],ans,res[(int)(2e6+100)];
  20. il void add(re int u,re int v){e[++cnt]=(Edge){v,h[u]};h[u]=cnt;++d[u];}
  21. il ll gi()
  22. {
  23. re ll x=0,t=1;
  24. re char ch=getchar();
  25. while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
  26. if(ch=='-') t=-1,ch=getchar();
  27. while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
  28. return x*t;
  29. }
  30. il ll ksm(re ll S,re ll o)
  31. {
  32. re ll T=S;S=1;
  33. while(o)
  34. {
  35. if(o&1) S=S*T%mod;
  36. T=T*T%mod;
  37. o>>=1;
  38. }
  39. return S;
  40. }
  41. il void dfs(re int u,re int fa,re int S)
  42. {
  43. if((1<<u-1)&S) {A[u]=B[u]=0;return;}
  44. re ll a=0,b=0;
  45. for(re int i=h[u];i+1;i=e[i].nxt)
  46. {
  47. re int v=e[i].to;
  48. if(v==fa) continue;
  49. dfs(v,u,S);
  50. (a+=A[v])%=mod;(b+=B[v])%=mod;
  51. }
  52. re ll ysn=ksm((d[u]-a+mod)%mod,mod-2);
  53. A[u]=ysn;
  54. B[u]=(d[u]+b)*ysn%mod;
  55. }
  56. il void Min_Max(re int x,re int sz,re int S)
  57. {
  58. if(x>k)
  59. {
  60. if(sz&1) (ans+=res[S])%=mod;
  61. else ans=(ans+mod-res[S])%mod;
  62. return;
  63. }
  64. Min_Max(x+1,sz,S);
  65. Min_Max(x+1,sz+1,S|(1<<q[x]-1));
  66. }
  67. int main()
  68. {
  69. memset(h,-1,sizeof(h));
  70. n=gi();Q=gi();rt=gi();mx=(1<<n)-1;
  71. fp(i,1,n-1)
  72. {
  73. re int u=gi(),v=gi();
  74. add(u,v);add(v,u);
  75. }
  76. fp(S,1,mx)
  77. {
  78. fp(i,1,n) A[i]=B[i]=0;
  79. dfs(rt,0,S);
  80. res[S]=B[rt];
  81. }
  82. while(Q--)
  83. {
  84. k=gi();ans=0;
  85. fp(i,1,k) q[i]=gi();
  86. Min_Max(1,0,0);
  87. printf("%lld\n",ans);
  88. }
  89. return 0;
  90. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注