[HNOI2011]XOR和路径

[HNOI2011]XOR和路径

给出一个n个点无向联通图以及其m条正整数边权,每次可以从一个顶点等概率选择一条出边,进入下一个顶点,定义一条路径的长度为该路径的异或和,询问从节点1到n的路径长度的期望,(N≤100,M≤100000)

异或和自然想到线性基这一有力工具,而样本空间无限,自然使用期望代无限状态的方法,再加之概率不固定,考虑倒推,而异或不满足加和,这对期望是致命的,于是考虑二进制拆分,对边权的第k为考虑,于是设(E(x))为从x到终点n的路径该位为1的概率,y为x的出边,(dis[x][y])为x,y连边的边权的第k为上的数字,于是我们会有

[E(x)=sum_{dis[x][y]==1}(1-E(y))+sum_{dis[x][y]==0}E(y) ]

于是我们可以的到一个异或方程组,利用高斯消元,解出其值,结果乘上(2^k),对于每一位这样处理,累加结果即可。

参考代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#define il inline
#define ri register
#define db long double
#define exact 0.00000001
using namespace std;
struct base{
    db base[101];
}A[101],*B[101];
struct point{
    point*next;int to,len;
}*pt,*head[101];
int out[101],n;db ans;
il void link(int,int,int),
    read(int&),insert(base&),eam();
template<class free>il free Abs(free);
int main(){
    int m,i,j,k;
    read(n),read(m);
    while(m--){
        read(i),read(j),read(k);
        link(i,j,k),++out[j];
        if(i!=j)link(j,i,k),++out[i];
    }
    for(i=0;i<=31;++i){
        memset(A,0,sizeof(A)),memset(B,0,sizeof(B));
        for(j=1;j<n;++j){
            A[j].base[j]=out[j];
            for(pt=head[j];pt!=NULL;pt=pt->next)
                if(pt->len>>i&1)++A[j].base[pt->to],++A[j].base[0];
                else --A[j].base[pt->to];insert(A[j]);
        }A[n].base[n]=1,insert(A[n]);
        ans+=(1<<i)*B[1]->base[0];
    }printf("%.3Lf",ans);
    return 0;
}
template<class free>
il free Abs(free x){
    return x<0?-x:x;
}
il void insert(base &x){
    ri int i,j;
    for(i=n;i;--i)
        if(Abs(x.base[i])>exact){
            if(B[i]==NULL){
                for(j=0;j<=i;++j)
                    x.base[j]/=x.base[i];
                return (void)(B[i]=&x);
            }
            for(j=0;j<=i;++j)
                x.base[j]-=B[i]->base[j]*x.base[i];
        }
}
il void read(int &x){
    x&=0;ri char c;while(c=getchar(),c<'0'||c>'9');
    while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
}
il void link(int x,int y,int z){
    pt=new point,pt->to=y,pt->len=z;
    pt->next=head[x],head[x]=pt;
}

原文地址:https://www.cnblogs.com/a1b3c7d9/p/10869029.html