Luogu3211[HNOI2011]XOR和路径
题面:洛谷
解析
这种位运算的题都是套路啊。很明显将边权拆位,列出转移方程高斯消元计算出每一位为1的期望,再累加贡献即可。
代码
// luogu-judger-enable-o2
#include<cstdio>
#include<cstring>
#include<iostream>
#define N 105
#define M 10005
using namespace std;
int n,m; double ans=0.0;
inline int In(){
char c=getchar(); int x=0,ft=1;
for(;c<'0'||c>'9';c=getchar()) if(c=='-') ft=-1;
for(;c>='0'&&c<='9';c=getchar()) x=x*10+c-'0';
return x*ft;
}
int h[N],deg[N],e_tot=0;
struct E{ int to,nex,d; }e[M<<1];
inline void add(int u,int v,int w){
e[++e_tot]=(E){v,h[u],w}; h[u]=e_tot; ++deg[u];
}
double a[N][N],x[N];
int main(){
// freopen("1.in","r",stdin);
// freopen("test.out","w",stdout);
n=In(); m=In();
for(int i=1,u,v,w;i<=m;++i){
u=In(); v=In(); w=In();
if(u==v) add(u,v,w);
else add(u,v,w),add(v,u,w);
}
for(int p=0;p<30;++p){
memset(a,0,sizeof(a));
for(int u=1;u<n;++u){
a[u][u]=1.0; double w=1.0/deg[u];
for(int i=h[u],v;i;i=e[i].nex){
v=e[i].to; bool op=e[i].d&(1<<p);
if(op) a[u][v]+=w,a[u][n+1]+=w;
else a[u][v]-=w;
}
}
a[n][n]=1.0;
for(int i=1;i<=n;++i)
for(int j=i+1;j<=n;++j)
for(int k=n+1;k>=i;--k)
a[j][k]-=a[i][k]*a[j][i]/a[i][i];
for(int i=n;i;--i){
x[i]=a[i][n+1];
for(int j=n;j>i;--j) x[i]-=a[i][j]*x[j];
x[i]/=a[i][i];
}
ans+=x[1]*(1<<p);
}
printf("%.3lf
",ans);
return 0;
}