Problem
Solution
可能是第一次两分钟想出HNOI的题
考虑到直接求解异或和很麻烦(如果dalao能直接做当我没说),套路拆分二进制位,对于每一个二进制位单独考虑,则 ans=∑t=2kE(n)∗t a n s = ∑ t = 2 k E ( n ) ∗ t
则如果权值只有0和1,则可以使用最基本的高斯消元求解(和HNOI那道游走差不多),总复杂度 O(n3log2maxval) O ( n 3 log 2 m a x v a l )
注意在自环时特判一下,卡卡精度即可
最近题解越写越短了
Code
#include<algorithm>
#include<cctype>
#include<cstdio>
using namespace std;
typedef long long ll;
#define rg register
#define cl(x) memset(x,0,sizeof(x))
template <typename _Tp> inline _Tp read(_Tp&x){
rg char c11=getchar(),ob=0;x=0;
while(c11^'-'&&!isdigit(c11))c11=getchar();if(c11=='-')c11=getchar(),ob=1;
while(isdigit(c11))x=x*10+c11-'0',c11=getchar();if(ob)x=-x;return x;
}
const int N=102,M=10010;
struct Edge{int v,nxt,w;}a[M<<1];
int head[N],deg[N];
double d[N][N];
int n,m,_,mxt;
inline void add(int u,int v,int w){a[++_].v=v,a[_].w=w,a[_].nxt=head[u],head[u]=_;}
void gauss(){
for(rg int i=1;i<=n;++i){
int p=i;
for(rg int j=i+1;j<=n;++j)if(d[j][i]>d[p][i])p=j;
if(p!=i)for(rg int j=i;j<=n+1;++j)swap(d[i][j],d[p][j]);
double t=d[i][i];
for(rg int j=i;j<=n+1;++j)d[i][j]/=t;
for(rg int j=1;j<=n;++j)if(j!=i&&d[j][i]!=0){
t=d[j][i];
for(rg int k=i;k<=n+1;++k)d[j][k]-=t*d[i][k];
}
}return ;
}
int main(){
read(n),read(m);
for(rg int i=0,x,y,z;i<m;++i){
read(x),read(y),read(z);add(x,y,z),++deg[x];
if(x!=y)add(y,x,z),++deg[y];
mxt=max(mxt,z);
}
double Ans(0);
for(rg int t=1;t<=mxt;t<<=1){
for(rg int i=1;i<=n;++i)
for(rg int j=1;j<=n+1;++j)d[i][j]=0;
d[n][n]=1;
for(rg int x=1;x<n;++x){
d[x][x]=deg[x];
for(rg int i=head[x];i;i=a[i].nxt)
if(a[i].w&t)++d[x][a[i].v],++d[x][n+1];
else --d[x][a[i].v];
}
gauss();
Ans+=1.0*d[1][n+1]*t;
}
printf("%.3lf\n",Ans);
return 0;
}