按位考虑。f[i]表示从i->n为1的期望。
注意并不用记两个,因为1-f[i]就是i->n为0的期望。
列出式子高消。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define maxv 150 #define maxe 20050 #define eps 1e-9 using namespace std; int n,m,nume=1,g[maxv],x,y,z,d[maxv]; double a[maxv][maxv],ans=0; struct edge { int v,bit[32],nxt; }e[maxe]; void addedge(int u,int v,int w) { e[++nume].v=v;e[nume].nxt=g[u];g[u]=nume; int ret=0; while (w) {e[nume].bit[ret]=w&1;w>>=1;ret++;} } void Gauss() { for (int i=1;i<=n;i++) { int id=i;double st=-1.0; for (int j=i;j<=n;j++) if (fabs(a[j][i])+eps>st) {st=fabs(a[j][i]);id=j;} if (id!=i) for (int j=1;j<=n+1;j++) swap(a[id][j],a[i][j]); double t=a[i][i]; for (int j=1;j<=n+1;j++) a[i][j]/=t; for (int j=1;j<=n;j++) { if (j==i) continue; double t=a[j][i]/a[i][i]; for (int k=1;k<=n+1;k++) a[j][k]-=t*a[i][k]; } } } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=m;i++) { scanf("%d%d%d",&x,&y,&z);d[x]++;if (x!=y) d[y]++; addedge(x,y,z);if (x!=y) addedge(y,x,z); } for (int t=0;t<=30;t++) { for (int i=1;i<=n+1;i++) for (int j=1;j<=n+1;j++) a[i][j]=0; for (int i=1;i<=n-1;i++) { for (int j=g[i];j;j=e[j].nxt) { int v=e[j].v; if (e[j].bit[t]) {a[i][v]+=1.0/d[i];a[i][n+1]+=1.0/d[i];} else a[i][v]-=1.0/d[i]; } a[i][i]+=1.0; } a[n][n]=1.0; Gauss(); ans+=a[1][n+1]*(1<<t); } printf("%.3f\n",ans); return 0; }