ABC F - Graph Smoothing 題解
阿新 • • 發佈:2021-11-10
link
給出一張圖,\(N\) 個點 \(M\) 條邊,每個點有一個初始權值 \(a_i\)
接下來有 \(K\) 次操作,每次相互獨立
- 隨機選中一條邊 \(<u,v>\),將 \(a_u\) 和 \(a_v\) 修改成\((a_u+a_v)/2\)
求出最後每個點的期望大小
solve
分別考慮 \(a_i\) 對自己的影響和其他的影響
設 \(d_i\) 為 \(i\) 的度
- 自己最自己影響
對於一個點,本來對他自己的貢獻是 \(a_i\) ,但是由於和他連線的有 \(d_i\) 條邊,所以他們被選中的概率是 \(d_i\over m\)
所以概率矩陣 \(a[i][i]= 1-{d_i\over {m\times 2}}\)
- 和自己連邊的點對自己的貢獻
對於任意一條邊 \(<u,v>\),顯然選擇到該邊的概率為 \(1\over m\) ,一條邊對自己的概率的影響是 \(1\over m\) ,所以概率矩陣 \(a[i][j]=1\over{2\times m}\)
剩下的就是矩陣快速冪,算出 \(k\)
code
#include<bits/stdc++.h> using namespace std; typedef long long LL; const int maxn=105; const LL TT=1e9+7; int N,du[maxn],M,K,a[maxn]; LL ans; struct Matrix{ int V[maxn][maxn]; Matrix(){memset(V,0,sizeof V);} friend Matrix operator *(Matrix A,Matrix B){ Matrix C; for(int i=1;i<=N;i++) for(int j=1;j<=N;j++) for(int k=1;k<=N;k++) C.V[i][j]=(C.V[i][j]+1LL*A.V[i][k]*B.V[k][j])%TT; return C; } }E,G; inline int read(){ int ret=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();} while(ch<='9'&&ch>='0')ret=ret*10+ch-'0',ch=getchar(); return ret*f; } int Pow(int a,int b){ int s=1,w=a; while(b){ if(b&1)s=1LL*s*w%TT;w=1LL*w*w%TT;b>>=1; } return s; } int main(){ freopen("F - Graph Smoothing.in","r",stdin); freopen("F - Graph Smoothing.out","w",stdout); N=read();M=read();K=read(); for(int i=1;i<=N;i++) a[i]=read(); for(int i=1;i<=M;i++){ int x=read(),y=read(); E.V[x][y]=E.V[y][x]=1; du[x]++;du[y]++; } int Inv_2m=Pow(2*M,TT-2); for(int i=1;i<=N;i++){ for(int j=1;j<=N;j++)if(E.V[i][j]) E.V[i][j]=Inv_2m; E.V[i][i]=(1ll*2*M-du[i])*Inv_2m%TT; } for(int i=1;i<=N;i++) G.V[i][i]=1; while(K){ if(K&1) G=G*E; E=E*E; K>>=1; } for(int i=1;i<=N;i++){ ans=0; for(int j=1;j<=N;j++) ans=(ans+(1ll*G.V[j][i]*a[j])%TT)%TT; printf("%lld\n",ans); } return 0; }