日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

「PKUWC2018」随机游走

發布時間:2024/4/15 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 「PKUWC2018」随机游走 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Min-Max容斥真好用

LOJ #2542

題意:給一棵不超過1818個節點的樹,50005000次詢問,每次問從根隨機游走走遍一個集合的期望步數


Solution:

考慮Min-Max容斥

Max(S)=T?S(?1)|T|+1Min(T)

其中S,T是一個集合,Max(S)表示S中最大元素,Min(S)同理

我們設集合S表示走到每個點的期望時間

顯然走遍一個集合的期望時間就是Max(S)

且第一次走到某集合的期望時間是Min(S)

Max(S)不容易計算,我們轉而求解Min(S)

fi表示從點i隨機游走第一次走到集合SS的期望步數

這個顯然可以高斯消元,不過復雜度略大

由于轉移是在樹上,可以直接在樹上O(n)消元

我們令fi=ki?f?fa[i]+bi

ii在集合S中的時候ki=bi=0否則進行轉移

轉移的時候把當前點孩子的kb算出然后代到當前點的方程中算出當前點的k和b

這樣可以在O(2n?n?)的時間復雜度內算出所有的Min(S)

?

然后直接容斥算Max(S),復雜度是5000?2n

我們可以提前預處理每個Max(S)每次枚舉子集轉移,時間復雜度是3^n的

據說都能過

不過其實這部分可以優化到2n?n

我們直接根據popcount(S)的奇偶性來判斷是否給Min(S)乘上?1

然后直接高維前綴和即可

#include<iostream> #include<cmath> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #define mod 998244353 #define ll long long using namespace std; struct ret{int k,b;ret operator +(const ret s)const{return {(k+s.k)%mod,(b+s.b)%mod};}ret operator *(const int s)const{return {(ll)k*s%mod,1ll*b*s%mod};} }f[19][1<<18]; const int N=50; int i,j,k,m,n,x,z,cnt,root,Q; int g[N],l[N],c[N],a[N],d[N],inv[N],Min[1<<18]; void add(int x,int y){a[++k]=y;if (!g[x]) g[x]=k;else c[l[x]]=k;l[x]=k; } int pow(int x,int y){int ans=1;for (int i=y;i;i>>=1,x=(ll)x*x%mod)if (i&1) ans=(ll)x*ans%mod;;return (ans+mod)%mod; } ret dfs(int x,int pre,int s){if (s>>x-1&1) return{0,0}; ret now={0,0};for (int i=g[x];i;i=c[i])if (a[i]!=pre) now=now+dfs(a[i],x,s)*inv[d[x]];const int Inv=pow(1-now.k,mod-2);return {(ll)Inv*inv[d[x]]%mod,1ll*Inv*(now.b+1)%mod}; } int main(){scanf("%d",&n);scanf("%d%d",&Q,&root);inv[0]=inv[1]=1;for (int i=2;i<=18;i++) inv[i]=(ll)inv[mod%i]*(mod-mod/i)%mod;for (int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);add(u,v);add(v,u);d[u]++;d[v]++;}for (int i=1;i<(1<<n);i++){ret ans=dfs(root,root,i);Min[i]=ans.b*(__builtin_popcount(i)&1?1:-1);}for (int i=0;i<n;i++)for (int j=0;j<1<<n;j++)if (j>>i&1) (Min[j]+=Min[j^(1<<i)])%=mod;while (Q--){int sum=0;scanf("%d",&x);for(int i=1;i<=x;i++) {int y;scanf("%d",&y);sum|=(1<<y-1);}printf("%d\n",(Min[sum]+mod)%mod);}return 0; } View Code

?

轉載于:https://www.cnblogs.com/zzrblogs/p/11196464.html

超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生

總結

以上是生活随笔為你收集整理的「PKUWC2018」随机游走的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。