bzoj2337 XOR和路径
题目大意:无向图中,每个点等概率的选择周围的点走过去,求1~n路径权值(走过边的异或和)的期望。
思路:对边权的二进制每一位单独考虑,因为异或后互不影响。设f[i]表示i~n的路径权值为1的概率,对于每一个点列出方程(注意边权为0/1),高斯消元求出答案。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxnode 20005 #define maxn 105 #define up 30 using namespace std; struct use{ double num[maxn]; }a[maxn],b; int point[maxn]={0},next[maxnode]={0},en[maxnode]={0},va[maxnode][50]={0},tot=0, mi[50]={0},du[maxn]={0},n; void add(int u,int v,int w) { int i=0,x; ++tot;next[tot]=point[u];point[u]=tot;en[tot]=v; x=w;i=0; while(x) {va[tot][++i]=x%2;x/=2;} if (u==v) return; ++tot;next[tot]=point[v];point[v]=tot;en[tot]=u; x=w;i=0; while(x) {va[tot][++i]=x%2;x/=2;} } void gauss() { int i,j,k;double t; for (i=1;i<=n;++i) { if (a[i].num[i]==0) for (j=i+1;j<=n;++j) if (a[j].num[i]!=0){swap(a[i],a[j]);break;} for (j=i+1;j<=n;++j) { t=a[j].num[i]*1.0/a[i].num[i]; for (k=1;k<=n+1;++k) a[j].num[k]-=a[i].num[k]*t; } } for (i=n;i>=1;--i) { b.num[i]=a[i].num[n+1]*1.0/a[i].num[i]; for (j=i-1;j>=1;--j) { a[j].num[n+1]-=b.num[i]*a[j].num[i]; a[j].num[i]=0; } } } int main() { int i,j,m,u,v,w,t;double ans=0; mi[1]=1; for (i=2;i<=up;++i) mi[i]=mi[i-1]*2; scanf("%d%d",&n,&m); for (i=1;i<=m;++i) { scanf("%d%d%d",&u,&v,&w);add(u,v,w); ++du[u];if (u!=v) ++du[v]; } for (t=1;t<=up;++t) { memset(a,0,sizeof(a)); memset(b.num,0,sizeof(b.num)); for (i=1;i<n;++i) { a[i].num[i]=-du[i]; for (j=point[i];j;j=next[j]) { if (va[j][t]==0) ++a[i].num[en[j]]; else { --a[i].num[en[j]];--a[i].num[n+1]; } } } a[n].num[n]=1; gauss();ans+=b.num[1]*mi[t]; } printf("%.3f\n",ans); }
时间: 2024-10-06 21:25:06