[HNOI2011]XOR和路径
BZOJ
luogu
感觉跟[HNOI2013]游走差不多a...
然而就是这个异或要一位一位做
设f[k][u]表示u点到n的路径异或和二进制第k位为1的概率
考虑枚举u的出边,w(u,v)表示这条边第k位是0还是1
[f[u]=sum_{w(u,v)=0}frac{f[v]}{d[u]}+sum_{w(u,v)=1}frac{1-f[v]}{d[u]}
]
处理好系数矩阵高斯消元
注意重自环只连单向边就行了
等等,还有f[n]=0
#include<bits/stdc++.h>
using namespace std;
const int _=105;
const double eps=1e-10;
int re(){
int x=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*w;
}
int n,m,cnt;
int h[_],d[_];
double Ans;
double a[_][_],b[_],ans[_];
struct edge{int to,next,w;}e[20005];
void link(int u,int v,int w){
e[++cnt]=(edge){v,h[u],w};
h[u]=cnt;d[u]++;
}
void gauss(){
for(int i=1;i<=n;i++){
if(fabs(a[i][i])<eps)
for(int j=i+1;j<=n;j++)
if(fabs(a[j][i])>eps){
swap(a[i],a[j]);swap(b[i],b[j]);break;
}
if(fabs(a[i][i])<eps)continue;
for(int j=i+1;j<=n;j++){
if(fabs(a[j][i])<eps)continue;
double s=a[j][i]/a[i][i];
for(int k=i;k<=n;k++)a[i][k]*=s;b[i]*=s;
for(int k=i;k<=n;k++)a[j][k]-=a[i][k];b[j]-=b[i];
}
}
for(int i=n;i>=1;i--){
ans[i]=b[i]/a[i][i];
for(int j=1;j<i;j++)b[j]-=a[j][i]*ans[i];
}
}
int main(){
n=re(),m=re();
for(int i=1,u,v,w;i<=m;i++){
u=re(),v=re(),w=re();
if(u^v)link(u,v,w),link(v,u,w);
else link(u,v,w);
}
for(int k=0;k<=29;k++){
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(ans,0,sizeof(ans));
for(int i=1;i<n;i++){
a[i][i]=1;
for(int j=h[i];j;j=e[j].next){
int v=e[j].to;
if(e[j].w>>k&1)a[i][v]+=1.0/d[i],b[i]+=1.0/d[i];
else a[i][v]-=1.0/d[i];
}
}
a[n][n]=1;gauss();Ans+=(1<<k)*ans[1];
}
printf("%.3f
",Ans);return 0;
}